Version 3.0: January 1, 1999
- Transparent proxying support added. - PPTP redirecting support added based on patches contributed by Dru Nelson <dnelson@redwoodsoft.com>. Submitted by: Charles Mott <cmott@srv.net>
This commit is contained in:
parent
2704b2cb2b
commit
7d96f4efd2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=44307
@ -127,3 +127,8 @@ Version 2.5: December, 1997 (ee)
|
||||
|
||||
Version 2.6: May, 1998 (amurai)
|
||||
- Added supporting routine for NetBios over TCP/IP.
|
||||
|
||||
Version 3.0: January 1, 1999
|
||||
- Transparent proxying support added.
|
||||
- PPTP redirecting support added based on patches
|
||||
contributed by Dru Nelson <dnelson@redwoodsoft.com>.
|
||||
|
@ -1,11 +1,11 @@
|
||||
# $Id$
|
||||
# $Id: Makefile,v 1.9 1998/08/31 12:14:30 brian Exp $
|
||||
|
||||
LIB= alias
|
||||
SHLIB_MAJOR= 2
|
||||
SHLIB_MINOR= 5
|
||||
SHLIB_MAJOR= 3
|
||||
SHLIB_MINOR= 0
|
||||
CFLAGS+= -Wall -I${.CURDIR}
|
||||
SRCS= alias.c alias_cuseeme.c alias_db.c alias_ftp.c alias_irc.c \
|
||||
alias_nbt.c alias_old.c alias_util.c
|
||||
alias_nbt.c alias_proxy.c alias_util.c
|
||||
MAN3= libalias.3
|
||||
|
||||
beforeinstall:
|
||||
|
@ -93,6 +93,10 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#ifndef IPPROTO_GRE
|
||||
#define IPPROTO_GRE 47
|
||||
#endif
|
||||
|
||||
#include "alias_local.h"
|
||||
#include "alias.h"
|
||||
|
||||
@ -104,38 +108,13 @@
|
||||
#define IRC_CONTROL_PORT_NUMBER_2 6668
|
||||
#define CUSEEME_PORT_NUMBER 7648
|
||||
|
||||
/*
|
||||
The following macro is used to update an
|
||||
internet checksum. "delta" is a 32-bit
|
||||
accumulation of all the changes to the
|
||||
checksum (adding in new 16-bit words and
|
||||
subtracting out old words), and "cksum"
|
||||
is the checksum value to be updated.
|
||||
*/
|
||||
#define ADJUST_CHECKSUM(acc, cksum) { \
|
||||
acc += cksum; \
|
||||
if (acc < 0) \
|
||||
{ \
|
||||
acc = -acc; \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) ~acc; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) acc; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* TCP Handling Routines
|
||||
|
||||
TcpMonitorIn() -- These routines monitor TCP connections, and
|
||||
TcpMonitorOut() -- delete a link node when a connection is closed.
|
||||
TcpMonitorOut() delete a link when a connection is closed.
|
||||
|
||||
These routines look for SYN, ACK and RST flags to determine when TCP
|
||||
connections open and close. When a TCP connection closes, the data
|
||||
@ -406,7 +385,6 @@ fragment contained in ICMP data section */
|
||||
return(PKT_ALIAS_IGNORED);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
IcmpAliasIn3(struct ip *pip)
|
||||
{
|
||||
@ -429,6 +407,10 @@ IcmpAliasIn(struct ip *pip)
|
||||
int iresult;
|
||||
struct icmp *ic;
|
||||
|
||||
/* Return if proxy-only mode is enabled */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
iresult = PKT_ALIAS_IGNORED;
|
||||
@ -563,6 +545,10 @@ IcmpAliasOut(struct ip *pip)
|
||||
int iresult;
|
||||
struct icmp *ic;
|
||||
|
||||
/* Return if proxy-only mode is enabled */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
iresult = PKT_ALIAS_IGNORED;
|
||||
@ -588,12 +574,73 @@ IcmpAliasOut(struct ip *pip)
|
||||
return(iresult);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
PptpAliasIn(struct ip *pip)
|
||||
{
|
||||
/*
|
||||
Handle incoming PPTP packets. The
|
||||
only thing which is done in this case is to alias
|
||||
the dest IP address of the packet to our inside
|
||||
machine.
|
||||
*/
|
||||
struct in_addr alias_addr;
|
||||
|
||||
if (!GetPptpAlias (&alias_addr))
|
||||
return PKT_ALIAS_IGNORED;
|
||||
|
||||
if (pip->ip_src.s_addr != alias_addr.s_addr) {
|
||||
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
(u_short *) &alias_addr,
|
||||
(u_short *) &pip->ip_dst,
|
||||
2);
|
||||
pip->ip_dst = alias_addr;
|
||||
}
|
||||
|
||||
return PKT_ALIAS_OK;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
PptpAliasOut(struct ip *pip)
|
||||
{
|
||||
/*
|
||||
Handle outgoing PPTP packets. The
|
||||
only thing which is done in this case is to alias
|
||||
the source IP address of the packet.
|
||||
*/
|
||||
struct in_addr alias_addr;
|
||||
|
||||
if (!GetPptpAlias (&alias_addr))
|
||||
return PKT_ALIAS_IGNORED;
|
||||
|
||||
if (pip->ip_src.s_addr == alias_addr.s_addr) {
|
||||
|
||||
alias_addr = FindAliasAddress(pip->ip_src);
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
(u_short *) &alias_addr,
|
||||
(u_short *) &pip->ip_src,
|
||||
2);
|
||||
pip->ip_src = alias_addr;
|
||||
}
|
||||
|
||||
return PKT_ALIAS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
UdpAliasIn(struct ip *pip)
|
||||
{
|
||||
struct udphdr *ud;
|
||||
struct alias_link *link;
|
||||
|
||||
/* Return if proxy-only mode is enabled */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
|
||||
@ -670,6 +717,10 @@ UdpAliasOut(struct ip *pip)
|
||||
struct udphdr *ud;
|
||||
struct alias_link *link;
|
||||
|
||||
/* Return if proxy-only mode is enabled */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
|
||||
@ -751,14 +802,18 @@ TcpAliasIn(struct ip *pip)
|
||||
{
|
||||
struct in_addr alias_address;
|
||||
struct in_addr original_address;
|
||||
struct in_addr proxy_address;
|
||||
u_short alias_port;
|
||||
u_short proxy_port;
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
alias_address = GetAliasAddress(link);
|
||||
original_address = GetOriginalAddress(link);
|
||||
proxy_address = GetProxyAddress(link);
|
||||
alias_port = tc->th_dport;
|
||||
tc->th_dport = GetOriginalPort(link);
|
||||
proxy_port = GetProxyPort(link);
|
||||
|
||||
/* Adjust TCP checksum since destination port is being unaliased */
|
||||
/* and destination port is being altered. */
|
||||
@ -771,6 +826,22 @@ TcpAliasIn(struct ip *pip)
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
/* If this is a proxy, then modify the tcp source port and
|
||||
checksum accumulation */
|
||||
if (proxy_port != 0)
|
||||
{
|
||||
accumulate += tc->th_sport;
|
||||
tc->th_sport = proxy_port;
|
||||
accumulate -= tc->th_sport;
|
||||
|
||||
sptr = (u_short *) &pip->ip_src;
|
||||
accumulate += *sptr++;
|
||||
accumulate += *sptr;
|
||||
sptr = (u_short *) &proxy_address;
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
}
|
||||
|
||||
/* See if ack number needs to be modified */
|
||||
if (GetAckModified(link) == 1)
|
||||
{
|
||||
@ -792,11 +863,28 @@ TcpAliasIn(struct ip *pip)
|
||||
ADJUST_CHECKSUM(accumulate, tc->th_sum);
|
||||
|
||||
/* Restore original IP address */
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
(u_short *) &original_address,
|
||||
(u_short *) &pip->ip_dst,
|
||||
2);
|
||||
sptr = (u_short *) &pip->ip_dst;
|
||||
accumulate = *sptr++;
|
||||
accumulate += *sptr;
|
||||
pip->ip_dst = original_address;
|
||||
sptr = (u_short *) &pip->ip_dst;
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
/* If this is a transparent proxy packet, then modify the source
|
||||
address */
|
||||
if (proxy_address.s_addr != 0)
|
||||
{
|
||||
sptr = (u_short *) &pip->ip_src;
|
||||
accumulate += *sptr++;
|
||||
accumulate += *sptr;
|
||||
pip->ip_src = proxy_address;
|
||||
sptr = (u_short *) &pip->ip_src;
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
}
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
|
||||
/* Monitor TCP connection state */
|
||||
TcpMonitorIn(pip, link);
|
||||
@ -809,39 +897,94 @@ TcpAliasIn(struct ip *pip)
|
||||
static int
|
||||
TcpAliasOut(struct ip *pip, int maxpacketsize)
|
||||
{
|
||||
int proxy_type;
|
||||
u_short dest_port;
|
||||
u_short proxy_server_port;
|
||||
struct in_addr dest_address;
|
||||
struct in_addr proxy_server_address;
|
||||
struct tcphdr *tc;
|
||||
struct alias_link *link;
|
||||
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
|
||||
|
||||
if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
/* If this is a transparent proxy, save original destination,
|
||||
then alter the destination and adust checksums */
|
||||
dest_port = tc->th_dport;
|
||||
dest_address = pip->ip_dst;
|
||||
if (proxy_type != 0)
|
||||
{
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
accumulate = tc->th_dport;
|
||||
tc->th_dport = proxy_server_port;
|
||||
accumulate -= tc->th_dport;
|
||||
|
||||
sptr = (u_short *) &(pip->ip_dst);
|
||||
accumulate += *sptr++;
|
||||
accumulate += *sptr;
|
||||
sptr = (u_short *) &proxy_server_address;
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, tc->th_sum);
|
||||
|
||||
sptr = (u_short *) &(pip->ip_dst);
|
||||
accumulate = *sptr++;
|
||||
accumulate += *sptr;
|
||||
pip->ip_dst = proxy_server_address;
|
||||
sptr = (u_short *) &(pip->ip_dst);
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
}
|
||||
|
||||
link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
|
||||
tc->th_sport, tc->th_dport,
|
||||
IPPROTO_TCP);
|
||||
if (link !=NULL)
|
||||
{
|
||||
struct in_addr alias_address;
|
||||
u_short alias_port;
|
||||
struct in_addr alias_address;
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
/* Save original destination address, if this is a proxy packet.
|
||||
Also modify packet to include destination encoding. */
|
||||
if (proxy_type != 0)
|
||||
{
|
||||
SetProxyPort(link, dest_port);
|
||||
SetProxyAddress(link, dest_address);
|
||||
ProxyModify(link, pip, maxpacketsize, proxy_type);
|
||||
}
|
||||
|
||||
/* Get alias address and port */
|
||||
alias_port = GetAliasPort(link);
|
||||
alias_address = GetAliasAddress(link);
|
||||
|
||||
/* Monitor tcp connection state */
|
||||
TcpMonitorOut(pip, link);
|
||||
|
||||
/* Special processing for ftp connection */
|
||||
/* Special processing for IP encoding protocols */
|
||||
if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
|
||||
|| ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
|
||||
AliasHandleFtpOut(pip, link, maxpacketsize);
|
||||
if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
|
||||
|| ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
|
||||
|| ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
|
||||
AliasHandleIrcOut(pip, link, maxpacketsize);
|
||||
|
||||
/* Adjust TCP checksum since source port is being aliased */
|
||||
/* and source address is being altered */
|
||||
accumulate = tc->th_sport;
|
||||
accumulate -= alias_port;
|
||||
tc->th_sport = alias_port;
|
||||
accumulate -= tc->th_sport;
|
||||
|
||||
sptr = (u_short *) &(pip->ip_src);
|
||||
accumulate += *sptr++;
|
||||
accumulate += *sptr;
|
||||
@ -869,15 +1012,16 @@ TcpAliasOut(struct ip *pip, int maxpacketsize)
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, tc->th_sum)
|
||||
|
||||
/* Put alias address in TCP header */
|
||||
tc->th_sport = alias_port;
|
||||
|
||||
/* Change source address */
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
(u_short *) &alias_address,
|
||||
(u_short *) &pip->ip_src,
|
||||
2);
|
||||
sptr = (u_short *) &(pip->ip_src);
|
||||
accumulate = *sptr++;
|
||||
accumulate += *sptr;
|
||||
pip->ip_src = alias_address;
|
||||
sptr = (u_short *) &(pip->ip_src);
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum)
|
||||
|
||||
return(PKT_ALIAS_OK);
|
||||
}
|
||||
@ -1031,6 +1175,9 @@ PacketAliasIn(char *ptr, int maxpacketsize)
|
||||
struct ip *pip;
|
||||
int iresult;
|
||||
|
||||
if (packetAliasMode & PKT_ALIAS_REVERSE)
|
||||
return PacketAliasOut(ptr, maxpacketsize);
|
||||
|
||||
HouseKeeping();
|
||||
ClearCheckNewLink();
|
||||
pip = (struct ip *) ptr;
|
||||
@ -1055,6 +1202,9 @@ PacketAliasIn(char *ptr, int maxpacketsize)
|
||||
case IPPROTO_TCP:
|
||||
iresult = TcpAliasIn(pip);
|
||||
break;
|
||||
case IPPROTO_GRE:
|
||||
iresult = PptpAliasIn(pip);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ntohs(pip->ip_off) & IP_MF)
|
||||
@ -1097,8 +1247,6 @@ PacketAliasIn(char *ptr, int maxpacketsize)
|
||||
#define UNREG_ADDR_C_LOWER 0xc0a80000
|
||||
#define UNREG_ADDR_C_UPPER 0xc0a8ffff
|
||||
|
||||
|
||||
|
||||
int
|
||||
PacketAliasOut(char *ptr, /* valid IP packet */
|
||||
int maxpacketsize /* How much the packet data may grow
|
||||
@ -1109,6 +1257,9 @@ PacketAliasOut(char *ptr, /* valid IP packet */
|
||||
struct in_addr addr_save;
|
||||
struct ip *pip;
|
||||
|
||||
if (packetAliasMode & PKT_ALIAS_REVERSE)
|
||||
return PacketAliasIn(ptr, maxpacketsize);
|
||||
|
||||
HouseKeeping();
|
||||
ClearCheckNewLink();
|
||||
pip = (struct ip *) ptr;
|
||||
@ -1153,6 +1304,9 @@ PacketAliasOut(char *ptr, /* valid IP packet */
|
||||
case IPPROTO_TCP:
|
||||
iresult = TcpAliasOut(pip, maxpacketsize);
|
||||
break;
|
||||
case IPPROTO_GRE:
|
||||
iresult = PptpAliasOut(pip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -7,7 +7,7 @@
|
||||
This software is placed into the public domain with no restrictions
|
||||
on its distribution.
|
||||
|
||||
$Id: alias.h,v 1.7 1998/01/16 12:56:07 bde Exp $
|
||||
$Id: alias.h,v 1.8 1998/04/19 21:42:05 brian Exp $
|
||||
*/
|
||||
|
||||
|
||||
@ -55,6 +55,10 @@ struct alias_link;
|
||||
struct in_addr, u_short,
|
||||
u_char);
|
||||
|
||||
extern int
|
||||
PacketAliasPptp(struct in_addr);
|
||||
|
||||
|
||||
extern struct alias_link *
|
||||
PacketAliasRedirectAddr(struct in_addr,
|
||||
struct in_addr);
|
||||
@ -82,28 +86,10 @@ struct alias_link;
|
||||
extern u_short
|
||||
PacketAliasInternetChecksum(u_short *, int);
|
||||
|
||||
/* Transparent Proxying */
|
||||
extern int
|
||||
PacketAliasProxyRule(char *);
|
||||
|
||||
/*
|
||||
In version 2.2, the function names were rationalized
|
||||
to all be of the form PacketAlias... These are the
|
||||
old function names for backwards compatibility
|
||||
*/
|
||||
extern int SaveFragmentPtr(char *);
|
||||
extern char *GetNextFragmentPtr(char *);
|
||||
extern void FragmentAliasIn(char *, char *);
|
||||
extern void SetPacketAliasAddress(struct in_addr);
|
||||
extern void InitPacketAlias(void);
|
||||
extern unsigned int SetPacketAliasMode(unsigned int, unsigned int);
|
||||
extern int PacketAliasIn2(char *, struct in_addr, int maxpacketsize);
|
||||
extern int PacketAliasOut2(char *, struct in_addr, int maxpacketsize);
|
||||
extern int
|
||||
PacketAliasPermanentLink(struct in_addr, u_short,
|
||||
struct in_addr, u_short,
|
||||
u_short, u_char);
|
||||
extern u_short InternetChecksum(u_short *, int);
|
||||
|
||||
/* Obsolete constant */
|
||||
#define PKT_ALIAS_NEW_LINK 5
|
||||
|
||||
/********************** Mode flags ********************/
|
||||
/* Set these flags using SetPacketAliasMode() */
|
||||
@ -138,7 +124,6 @@ extern u_short InternetChecksum(u_short *, int);
|
||||
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 */
|
||||
@ -162,6 +147,14 @@ extern u_short InternetChecksum(u_short *, int);
|
||||
#define PKT_ALIAS_PUNCH_FW 0x40
|
||||
#endif
|
||||
|
||||
/* If PKT_ALIAS_PROXY_ONLY is set, then NAT will be disabled and only
|
||||
transparent proxying performed */
|
||||
#define PKT_ALIAS_PROXY_ONLY 0x40
|
||||
|
||||
/* If PKT_ALIAS_REVERSE is set, the actions of PacketAliasIn()
|
||||
and PacketAliasOut() are reversed */
|
||||
#define PKT_ALIAS_REVERSE 0x80
|
||||
|
||||
/* Return Codes */
|
||||
#define PKT_ALIAS_ERROR -1
|
||||
#define PKT_ALIAS_OK 1
|
||||
|
@ -56,12 +56,12 @@
|
||||
Added ability to create an alias port without
|
||||
either destination address or port specified.
|
||||
port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
|
||||
|
||||
|
||||
Removed K&R style function headers
|
||||
and general cleanup. (ee)
|
||||
|
||||
Added packetAliasMode to replace compiler #defines's (ee)
|
||||
|
||||
|
||||
Allocates sockets for partially specified
|
||||
ports if ALIAS_USE_SOCKETS defined. (cjm)
|
||||
|
||||
@ -73,10 +73,10 @@
|
||||
links. (J. Fortes suggested the need for this.)
|
||||
Examples:
|
||||
|
||||
(192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
|
||||
(192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
|
||||
|
||||
(192.168.0.2, port 21) <-> alias port 3604, known dest addr
|
||||
unknown dest port
|
||||
unknown dest port
|
||||
|
||||
These permament links allow for incoming connections to
|
||||
machines on the local network. They can be given with a
|
||||
@ -111,7 +111,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
@ -139,7 +139,7 @@
|
||||
#define LINK_TABLE_IN_SIZE 4001
|
||||
|
||||
/* Parameters used for cleanup of expired links */
|
||||
#define ALIAS_CLEANUP_INTERVAL_SECS 60
|
||||
#define ALIAS_CLEANUP_INTERVAL_SECS 60
|
||||
#define ALIAS_CLEANUP_MAX_SPOKES 30
|
||||
|
||||
/* Timouts (in seconds) for different link types) */
|
||||
@ -174,14 +174,14 @@
|
||||
|
||||
/* Dummy port number codes used for FindLinkIn/Out() and AddLink().
|
||||
These constants can be anything except zero, which indicates an
|
||||
unknown port numbea. */
|
||||
unknown port number. */
|
||||
|
||||
#define NO_DEST_PORT 1
|
||||
#define NO_SRC_PORT 1
|
||||
|
||||
|
||||
|
||||
/* Data Structures
|
||||
/* Data Structures
|
||||
|
||||
The fundamental data structure used in this program is
|
||||
"struct alias_link". Whenever a TCP connection is made,
|
||||
@ -237,11 +237,13 @@ struct tcp_dat
|
||||
struct alias_link /* Main data structure */
|
||||
{
|
||||
struct in_addr src_addr; /* Address and port information */
|
||||
struct in_addr dst_addr; /* . */
|
||||
struct in_addr alias_addr; /* . */
|
||||
u_short src_port; /* . */
|
||||
u_short dst_port; /* . */
|
||||
u_short alias_port; /* . */
|
||||
struct in_addr dst_addr;
|
||||
struct in_addr alias_addr;
|
||||
struct in_addr proxy_addr;
|
||||
u_short src_port;
|
||||
u_short dst_port;
|
||||
u_short alias_port;
|
||||
u_short proxy_port;
|
||||
|
||||
int link_type; /* Type of link: tcp, udp, icmp, frag */
|
||||
|
||||
@ -348,6 +350,12 @@ static int fireWallFD = -1; /* File descriptor to be able to */
|
||||
/* flag. */
|
||||
#endif
|
||||
|
||||
static int pptpAliasFlag; /* Indicates if PPTP aliasing is */
|
||||
/* on or off */
|
||||
static struct in_addr pptpAliasAddr; /* Address of source of PPTP */
|
||||
/* packets. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -853,15 +861,17 @@ AddLink(struct in_addr src_addr,
|
||||
alias_addr.s_addr = 0;
|
||||
|
||||
/* Basic initialization */
|
||||
link->src_addr = src_addr;
|
||||
link->dst_addr = dst_addr;
|
||||
link->src_port = src_port;
|
||||
link->alias_addr = alias_addr;
|
||||
link->dst_port = dst_port;
|
||||
link->link_type = link_type;
|
||||
link->sockfd = -1;
|
||||
link->flags = 0;
|
||||
link->timestamp = timeStamp;
|
||||
link->src_addr = src_addr;
|
||||
link->dst_addr = dst_addr;
|
||||
link->alias_addr = alias_addr;
|
||||
link->proxy_addr.s_addr = 0;
|
||||
link->src_port = src_port;
|
||||
link->dst_port = dst_port;
|
||||
link->proxy_port = 0;
|
||||
link->link_type = link_type;
|
||||
link->sockfd = -1;
|
||||
link->flags = 0;
|
||||
link->timestamp = timeStamp;
|
||||
|
||||
/* Expiration time */
|
||||
switch (link_type)
|
||||
@ -1304,7 +1314,9 @@ FindUdpTcpIn(struct in_addr dst_addr,
|
||||
dst_port, alias_port,
|
||||
link_type, 1);
|
||||
|
||||
if ( !(packetAliasMode & PKT_ALIAS_DENY_INCOMING) && link == NULL)
|
||||
if (!(packetAliasMode & PKT_ALIAS_DENY_INCOMING)
|
||||
&& !(packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
&& link == NULL)
|
||||
{
|
||||
struct in_addr target_addr;
|
||||
|
||||
@ -1578,6 +1590,34 @@ SetAckModified(struct alias_link *link)
|
||||
}
|
||||
|
||||
|
||||
struct in_addr
|
||||
GetProxyAddress(struct alias_link *link)
|
||||
{
|
||||
return link->proxy_addr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SetProxyAddress(struct alias_link *link, struct in_addr addr)
|
||||
{
|
||||
link->proxy_addr = addr;
|
||||
}
|
||||
|
||||
|
||||
u_short
|
||||
GetProxyPort(struct alias_link *link)
|
||||
{
|
||||
return link->proxy_port;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SetProxyPort(struct alias_link *link, u_short port)
|
||||
{
|
||||
link->proxy_port = port;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
GetAckModified(struct alias_link *link)
|
||||
{
|
||||
@ -1906,6 +1946,26 @@ PacketAliasRedirectPort(struct in_addr src_addr, u_short src_port,
|
||||
return link;
|
||||
}
|
||||
|
||||
/* Translate PPTP packets to a machine on the inside
|
||||
*/
|
||||
int
|
||||
PacketAliasPptp(struct in_addr src_addr)
|
||||
{
|
||||
|
||||
pptpAliasAddr = src_addr; /* Address of the inside PPTP machine */
|
||||
pptpAliasFlag = 1;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetPptpAlias (struct in_addr* alias_addr)
|
||||
{
|
||||
if (pptpAliasFlag)
|
||||
*alias_addr = pptpAliasAddr;
|
||||
|
||||
return pptpAliasFlag;
|
||||
}
|
||||
|
||||
/* Static address translation */
|
||||
struct alias_link *
|
||||
@ -2007,6 +2067,8 @@ PacketAliasInit(void)
|
||||
packetAliasMode = PKT_ALIAS_SAME_PORTS
|
||||
| PKT_ALIAS_USE_SOCKETS
|
||||
| PKT_ALIAS_RESET_ON_ADDR_CHANGE;
|
||||
|
||||
pptpAliasFlag = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,9 +1,11 @@
|
||||
/* -*- 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
|
||||
as any future add-ons). It also includes macros, globals and
|
||||
struct definitions shared by more than one alias*.c file.
|
||||
|
||||
This include file 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.
|
||||
@ -15,9 +17,54 @@
|
||||
#ifndef ALIAS_LOCAL_H
|
||||
#define ALIAS_LOCAL_H
|
||||
|
||||
|
||||
/*
|
||||
Macros
|
||||
*/
|
||||
|
||||
/*
|
||||
The following macro is used to update an
|
||||
internet checksum. "delta" is a 32-bit
|
||||
accumulation of all the changes to the
|
||||
checksum (adding in new 16-bit words and
|
||||
subtracting out old words), and "cksum"
|
||||
is the checksum value to be updated.
|
||||
*/
|
||||
#define ADJUST_CHECKSUM(acc, cksum) { \
|
||||
acc += cksum; \
|
||||
if (acc < 0) \
|
||||
{ \
|
||||
acc = -acc; \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) ~acc; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) acc; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Globals
|
||||
*/
|
||||
|
||||
extern int packetAliasMode;
|
||||
|
||||
struct alias_link;
|
||||
|
||||
/*
|
||||
Structs
|
||||
*/
|
||||
|
||||
struct alias_link; /* Incomplete structure */
|
||||
|
||||
|
||||
/*
|
||||
Prototypes
|
||||
*/
|
||||
|
||||
/* General utilities */
|
||||
u_short IpChecksum(struct ip *);
|
||||
@ -71,6 +118,10 @@ struct in_addr GetDefaultAliasAddress(void);
|
||||
void SetDefaultAliasAddress(struct in_addr);
|
||||
u_short GetOriginalPort(struct alias_link *);
|
||||
u_short GetAliasPort(struct alias_link *);
|
||||
struct in_addr GetProxyAddress(struct alias_link *);
|
||||
void SetProxyAddress(struct alias_link *, struct in_addr);
|
||||
u_short GetProxyPort(struct alias_link *);
|
||||
void SetProxyPort(struct alias_link *, u_short);
|
||||
void SetAckModified(struct alias_link *);
|
||||
int GetAckModified(struct alias_link *);
|
||||
int GetDeltaAckIn(struct ip *, struct alias_link *);
|
||||
@ -88,13 +139,24 @@ void HouseKeeping(void);
|
||||
|
||||
/* Tcp specfic routines */
|
||||
/*lint -save -library Suppress flexelint warnings */
|
||||
|
||||
/* FTP routines */
|
||||
void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
|
||||
|
||||
/* IRC routines */
|
||||
void AliasHandleIrcOut(struct ip *pip, struct alias_link *link, int maxsize );
|
||||
|
||||
/* NetBIOS routines */
|
||||
int AliasHandleUdpNbt(struct ip *, struct alias_link *, struct in_addr *, u_short);
|
||||
int AliasHandleUdpNbtNS(struct ip *, struct alias_link *, struct in_addr *, u_short *, struct in_addr *, u_short *);
|
||||
|
||||
/* CUSeeMe routines */
|
||||
void AliasHandleCUSeeMeOut(struct ip *, struct alias_link *);
|
||||
void AliasHandleCUSeeMeIn(struct ip *, struct in_addr);
|
||||
|
||||
/* Transparent proxy routines */
|
||||
int ProxyCheck(struct ip *, struct in_addr *, u_short *);
|
||||
void ProxyModify(struct alias_link *, struct ip *, int, int);
|
||||
|
||||
|
||||
enum alias_tcp_state {
|
||||
@ -103,5 +165,6 @@ enum alias_tcp_state {
|
||||
ALIAS_TCP_STATE_DISCONNECTED
|
||||
};
|
||||
|
||||
int GetPptpAlias (struct in_addr*);
|
||||
/*lint -restore */
|
||||
#endif /* defined(ALIAS_LOCAL_H) */
|
||||
|
801
lib/libalias/alias_proxy.c
Normal file
801
lib/libalias/alias_proxy.c
Normal file
@ -0,0 +1,801 @@
|
||||
/* file: alias_proxy.c
|
||||
|
||||
This file encapsulates special operations related to transparent
|
||||
proxy redirection. This is where packets with a particular destination,
|
||||
usually tcp port 80, are redirected to a proxy server.
|
||||
|
||||
When packets are proxied, the destination address and port are
|
||||
modified. In certain cases, it is necessary to somehow encode
|
||||
the original address/port info into the packet. Two methods are
|
||||
presently supported: addition of a [DEST addr port] string at the
|
||||
beginning a of tcp stream, or inclusion of an optional field
|
||||
in the IP header.
|
||||
|
||||
There is one public API function:
|
||||
|
||||
PacketAliasProxyRule() -- Adds and deletes proxy
|
||||
rules.
|
||||
|
||||
Rules are stored in a linear linked list, so lookup efficiency
|
||||
won't be too good for large lists.
|
||||
|
||||
|
||||
Initial development: April, 1998 (cjm)
|
||||
*/
|
||||
|
||||
|
||||
/* System includes */
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/* BSD IPV4 includes */
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "alias_local.h" /* Functions used by alias*.c */
|
||||
#include "alias.h" /* Public API functions for libalias */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Data structures
|
||||
*/
|
||||
|
||||
/*
|
||||
* A linked list of arbitrary length, based on struct proxy_entry is
|
||||
* used to store proxy rules.
|
||||
*/
|
||||
struct proxy_entry
|
||||
{
|
||||
#define PROXY_TYPE_ENCODE_NONE 1
|
||||
#define PROXY_TYPE_ENCODE_TCPSTREAM 2
|
||||
#define PROXY_TYPE_ENCODE_IPHDR 3
|
||||
int rule_index;
|
||||
int proxy_type;
|
||||
u_char proto;
|
||||
u_short proxy_port;
|
||||
u_short server_port;
|
||||
|
||||
struct in_addr server_addr;
|
||||
|
||||
struct in_addr src_addr;
|
||||
struct in_addr src_mask;
|
||||
|
||||
struct in_addr dst_addr;
|
||||
struct in_addr dst_mask;
|
||||
|
||||
struct proxy_entry *next;
|
||||
struct proxy_entry *last;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
File scope variables
|
||||
*/
|
||||
|
||||
static struct proxy_entry *proxyList;
|
||||
|
||||
|
||||
|
||||
/* Local (static) functions:
|
||||
|
||||
IpMask() -- Utility function for creating IP
|
||||
masks from integer (1-32) specification.
|
||||
IpAddr() -- Utility function for converting string
|
||||
to IP address
|
||||
IpPort() -- Utility function for converting string
|
||||
to port number
|
||||
RuleAdd() -- Adds an element to the rule list.
|
||||
RuleDelete() -- Removes an element from the rule list.
|
||||
RuleNumberDelete() -- Removes all elements from the rule list
|
||||
having a certain rule number.
|
||||
ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning
|
||||
of a TCP stream.
|
||||
ProxyEncodeIpHeader() -- Adds an IP option indicating the true
|
||||
destination of a proxied IP packet
|
||||
*/
|
||||
|
||||
static int IpMask(int, struct in_addr *);
|
||||
static int IpAddr(char *, struct in_addr *);
|
||||
static int IpPort(char *, int, int *);
|
||||
static void RuleAdd(struct proxy_entry *);
|
||||
static void RuleDelete(struct proxy_entry *);
|
||||
static int RuleNumberDelete(int);
|
||||
static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int);
|
||||
static void ProxyEncodeIpHeader(struct ip *, int);
|
||||
|
||||
static int
|
||||
IpMask(int nbits, struct in_addr *mask)
|
||||
{
|
||||
int i;
|
||||
u_int imask;
|
||||
|
||||
if (nbits < 0 || nbits > 32)
|
||||
return -1;
|
||||
|
||||
imask = 0;
|
||||
for (i=0; i<nbits; i++)
|
||||
imask = (imask >> 1) + 0x80000000;
|
||||
mask->s_addr = htonl(imask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
IpAddr(char *s, struct in_addr *addr)
|
||||
{
|
||||
if (inet_aton(s, addr) == 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
IpPort(char *s, int proto, int *port)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = sscanf(s, "%d", port);
|
||||
if (n != 1)
|
||||
{
|
||||
struct servent *se;
|
||||
|
||||
if (proto == IPPROTO_TCP)
|
||||
se = getservbyname(s, "tcp");
|
||||
else if (proto == IPPROTO_UDP)
|
||||
se = getservbyname(s, "udp");
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (se == NULL)
|
||||
return -1;
|
||||
|
||||
*port = (u_int) ntohs(se->s_port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
RuleAdd(struct proxy_entry *entry)
|
||||
{
|
||||
int rule_index;
|
||||
struct proxy_entry *ptr;
|
||||
struct proxy_entry *ptr_last;
|
||||
|
||||
if (proxyList == NULL)
|
||||
{
|
||||
proxyList = entry;
|
||||
entry->last = NULL;
|
||||
entry->next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
rule_index = entry->rule_index;
|
||||
ptr = proxyList;
|
||||
ptr_last = NULL;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
if (ptr->rule_index >= rule_index)
|
||||
{
|
||||
if (ptr_last == NULL)
|
||||
{
|
||||
entry->next = proxyList;
|
||||
entry->last = NULL;
|
||||
proxyList->last = entry;
|
||||
proxyList = entry;
|
||||
return;
|
||||
}
|
||||
|
||||
ptr_last->next = entry;
|
||||
ptr->last = entry;
|
||||
entry->last = ptr->last;
|
||||
entry->next = ptr;
|
||||
return;
|
||||
}
|
||||
ptr_last = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
ptr_last->next = entry;
|
||||
entry->last = ptr_last;
|
||||
entry->next = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
RuleDelete(struct proxy_entry *entry)
|
||||
{
|
||||
if (entry->last != NULL)
|
||||
entry->last->next = entry->next;
|
||||
else
|
||||
proxyList = entry->next;
|
||||
|
||||
if (entry->next != NULL)
|
||||
entry->next->last = entry->last;
|
||||
|
||||
free(entry);
|
||||
}
|
||||
|
||||
static int
|
||||
RuleNumberDelete(int rule_index)
|
||||
{
|
||||
int err;
|
||||
struct proxy_entry *ptr;
|
||||
|
||||
err = -1;
|
||||
ptr = proxyList;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
struct proxy_entry *ptr_next;
|
||||
|
||||
ptr_next = ptr->next;
|
||||
if (ptr->rule_index == rule_index)
|
||||
{
|
||||
err = 0;
|
||||
RuleDelete(ptr);
|
||||
}
|
||||
|
||||
ptr = ptr_next;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
ProxyEncodeTcpStream(struct alias_link *link,
|
||||
struct ip *pip,
|
||||
int maxpacketsize)
|
||||
{
|
||||
int slen;
|
||||
char buffer[40];
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Compute pointer to tcp header */
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
/* Don't modify if once already modified */
|
||||
|
||||
if (GetAckModified (link))
|
||||
return;
|
||||
|
||||
/* Translate destination address and port to string form */
|
||||
snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]",
|
||||
inet_ntoa(GetProxyAddress (link)), (u_int) ntohs(GetProxyPort (link)));
|
||||
|
||||
/* Pad string out to a multiple of two in length */
|
||||
slen = strlen(buffer);
|
||||
switch (slen % 2)
|
||||
{
|
||||
case 0:
|
||||
strcat(buffer, " \n");
|
||||
slen += 2;
|
||||
break;
|
||||
case 1:
|
||||
strcat(buffer, "\n");
|
||||
slen += 1;
|
||||
}
|
||||
|
||||
/* Check for packet overflow */
|
||||
if ((ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize)
|
||||
return;
|
||||
|
||||
/* Shift existing TCP data and insert destination string */
|
||||
{
|
||||
int dlen;
|
||||
int hlen;
|
||||
u_char *p;
|
||||
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
dlen = ntohs (pip->ip_len) - hlen;
|
||||
|
||||
/* Modify first packet that has data in it */
|
||||
|
||||
if (dlen == 0)
|
||||
return;
|
||||
|
||||
p = (char *) pip;
|
||||
p += hlen;
|
||||
|
||||
memmove(p + slen, p, dlen);
|
||||
memcpy(p, buffer, slen);
|
||||
}
|
||||
|
||||
/* Save information about modfied sequence number */
|
||||
{
|
||||
int delta;
|
||||
|
||||
SetAckModified(link);
|
||||
delta = GetDeltaSeqOut(pip, link);
|
||||
AddSeq(pip, link, delta+slen);
|
||||
}
|
||||
|
||||
/* Update IP header packet length and checksum */
|
||||
{
|
||||
int accumulate;
|
||||
|
||||
accumulate = pip->ip_len;
|
||||
pip->ip_len = htons(ntohs(pip->ip_len) + slen);
|
||||
accumulate -= pip->ip_len;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
}
|
||||
|
||||
/* Update TCP checksum, Use TcpChecksum since so many things have
|
||||
already changed. */
|
||||
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum (pip);
|
||||
}
|
||||
|
||||
static void
|
||||
ProxyEncodeIpHeader(struct ip *pip,
|
||||
int maxpacketsize)
|
||||
{
|
||||
#define OPTION_LEN_BYTES 8
|
||||
#define OPTION_LEN_INT16 4
|
||||
#define OPTION_LEN_INT32 2
|
||||
u_char option[OPTION_LEN_BYTES];
|
||||
|
||||
fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip));
|
||||
fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip));
|
||||
|
||||
/* Check to see that there is room to add an IP option */
|
||||
if (pip->ip_hl > (0x0f - OPTION_LEN_INT32))
|
||||
return;
|
||||
|
||||
/* Build option and copy into packet */
|
||||
{
|
||||
u_char *ptr;
|
||||
struct tcphdr *tc;
|
||||
|
||||
ptr = (u_char *) pip;
|
||||
ptr += 20;
|
||||
memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20);
|
||||
|
||||
option[0] = 0x64; /* class: 3 (reserved), option 4 */
|
||||
option[1] = OPTION_LEN_BYTES;
|
||||
|
||||
memcpy(&option[2], (u_char *) &pip->ip_dst, 4);
|
||||
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
memcpy(&option[6], (u_char *) &tc->th_sport, 2);
|
||||
|
||||
memcpy(ptr, option, 8);
|
||||
}
|
||||
|
||||
/* Update checksum, header length and packet length */
|
||||
{
|
||||
int i;
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
sptr = (u_short *) option;
|
||||
accumulate = 0;
|
||||
for (i=0; i<OPTION_LEN_INT16; i++)
|
||||
accumulate -= *(sptr++);
|
||||
|
||||
sptr = (u_short *) pip;
|
||||
accumulate += *sptr;
|
||||
pip->ip_hl += OPTION_LEN_INT32;
|
||||
accumulate -= *sptr;
|
||||
|
||||
accumulate += pip->ip_len;
|
||||
pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES);
|
||||
accumulate -= pip->ip_len;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
}
|
||||
#undef OPTION_LEN_BYTES
|
||||
#undef OPTION_LEN_INT16
|
||||
#undef OPTION_LEN_INT32
|
||||
fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip));
|
||||
fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip));
|
||||
}
|
||||
|
||||
|
||||
/* Functions by other packet alias source files
|
||||
|
||||
ProxyCheck() -- Checks whether an outgoing packet should
|
||||
be proxied.
|
||||
ProxyModify() -- Encodes the original destination address/port
|
||||
for a packet which is to be redirected to
|
||||
a proxy server.
|
||||
*/
|
||||
|
||||
int
|
||||
ProxyCheck(struct ip *pip,
|
||||
struct in_addr *proxy_server_addr,
|
||||
u_short *proxy_server_port)
|
||||
{
|
||||
u_short dst_port;
|
||||
struct in_addr src_addr;
|
||||
struct in_addr dst_addr;
|
||||
struct proxy_entry *ptr;
|
||||
|
||||
src_addr = pip->ip_src;
|
||||
dst_addr = pip->ip_dst;
|
||||
dst_port = ((struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)))
|
||||
->th_dport;
|
||||
|
||||
ptr = proxyList;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
u_short proxy_port;
|
||||
|
||||
proxy_port = ptr->proxy_port;
|
||||
if ((dst_port == proxy_port || proxy_port == 0)
|
||||
&& pip->ip_p == ptr->proto
|
||||
&& src_addr.s_addr != ptr->server_addr.s_addr)
|
||||
{
|
||||
struct in_addr src_addr_masked;
|
||||
struct in_addr dst_addr_masked;
|
||||
|
||||
src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr;
|
||||
dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr;
|
||||
|
||||
if ((src_addr_masked.s_addr == ptr->src_addr.s_addr)
|
||||
&& (dst_addr_masked.s_addr == ptr->dst_addr.s_addr))
|
||||
{
|
||||
if ((*proxy_server_port = ptr->server_port) == 0)
|
||||
*proxy_server_port = dst_port;
|
||||
*proxy_server_addr = ptr->server_addr;
|
||||
return ptr->proxy_type;
|
||||
}
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ProxyModify(struct alias_link *link,
|
||||
struct ip *pip,
|
||||
int maxpacketsize,
|
||||
int proxy_type)
|
||||
{
|
||||
switch (proxy_type)
|
||||
{
|
||||
case PROXY_TYPE_ENCODE_IPHDR:
|
||||
ProxyEncodeIpHeader(pip, maxpacketsize);
|
||||
break;
|
||||
|
||||
case PROXY_TYPE_ENCODE_TCPSTREAM:
|
||||
ProxyEncodeTcpStream(link, pip, maxpacketsize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Public API functions
|
||||
*/
|
||||
|
||||
int
|
||||
PacketAliasProxyRule(char *cmd)
|
||||
{
|
||||
/*
|
||||
* This function takes command strings of the form:
|
||||
*
|
||||
* server <addr>[:<port>]
|
||||
* [port <port>]
|
||||
* [rule n]
|
||||
* [proto tcp|udp]
|
||||
* [src <addr>[/n]]
|
||||
* [dst <addr>[/n]]
|
||||
* [type encode_tcp_stream|encode_ip_hdr|no_encode]
|
||||
*
|
||||
* delete <rule number>
|
||||
*
|
||||
* Subfields can be in arbitrary order. Port numbers and addresses
|
||||
* must be in either numeric or symbolic form. An optional rule number
|
||||
* is used to control the order in which rules are searched. If two
|
||||
* rules have the same number, then search order cannot be guaranteed,
|
||||
* and the rules should be disjoint. If no rule number is specified,
|
||||
* then 0 is used, and group 0 rules are always checked before any
|
||||
* others.
|
||||
*/
|
||||
int i, n, len;
|
||||
int cmd_len;
|
||||
int token_count;
|
||||
int state;
|
||||
char *token;
|
||||
char buffer[256];
|
||||
char str_port[sizeof(buffer)];
|
||||
char str_server_port[sizeof(buffer)];
|
||||
|
||||
int rule_index;
|
||||
int proto;
|
||||
int proxy_type;
|
||||
int proxy_port;
|
||||
int server_port;
|
||||
struct in_addr server_addr;
|
||||
struct in_addr src_addr, src_mask;
|
||||
struct in_addr dst_addr, dst_mask;
|
||||
struct proxy_entry *proxy_entry;
|
||||
|
||||
/* Copy command line into a buffer */
|
||||
cmd_len = strlen(cmd);
|
||||
if (cmd_len > (sizeof(buffer) - 1))
|
||||
return -1;
|
||||
strcpy(buffer, cmd);
|
||||
|
||||
/* Convert to lower case */
|
||||
len = strlen(buffer);
|
||||
for (i=0; i<len; i++)
|
||||
buffer[i] = tolower(buffer[i]);
|
||||
|
||||
/* Set default proxy type */
|
||||
|
||||
/* Set up default values */
|
||||
rule_index = 0;
|
||||
proxy_type = PROXY_TYPE_ENCODE_NONE;
|
||||
proto = IPPROTO_TCP;
|
||||
proxy_port = 0;
|
||||
server_addr.s_addr = 0;
|
||||
server_port = 0;
|
||||
src_addr.s_addr = 0;
|
||||
IpMask(0, &src_mask);
|
||||
dst_addr.s_addr = 0;
|
||||
IpMask(0, &dst_mask);
|
||||
|
||||
str_port[0] = 0;
|
||||
str_server_port[0] = 0;
|
||||
|
||||
/* Parse command string with state machine */
|
||||
#define STATE_READ_KEYWORD 0
|
||||
#define STATE_READ_TYPE 1
|
||||
#define STATE_READ_PORT 2
|
||||
#define STATE_READ_SERVER 3
|
||||
#define STATE_READ_RULE 4
|
||||
#define STATE_READ_DELETE 5
|
||||
#define STATE_READ_PROTO 6
|
||||
#define STATE_READ_SRC 7
|
||||
#define STATE_READ_DST 8
|
||||
state = STATE_READ_KEYWORD;
|
||||
token = strtok(buffer, " \t");
|
||||
token_count = 0;
|
||||
while (token != NULL)
|
||||
{
|
||||
token_count++;
|
||||
switch (state)
|
||||
{
|
||||
case STATE_READ_KEYWORD:
|
||||
if (strcmp(token, "type") == 0)
|
||||
state = STATE_READ_TYPE;
|
||||
else if (strcmp(token, "port") == 0)
|
||||
state = STATE_READ_PORT;
|
||||
else if (strcmp(token, "server") == 0)
|
||||
state = STATE_READ_SERVER;
|
||||
else if (strcmp(token, "rule") == 0)
|
||||
state = STATE_READ_RULE;
|
||||
else if (strcmp(token, "delete") == 0)
|
||||
state = STATE_READ_DELETE;
|
||||
else if (strcmp(token, "proto") == 0)
|
||||
state = STATE_READ_PROTO;
|
||||
else if (strcmp(token, "src") == 0)
|
||||
state = STATE_READ_SRC;
|
||||
else if (strcmp(token, "dst") == 0)
|
||||
state = STATE_READ_DST;
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case STATE_READ_TYPE:
|
||||
if (strcmp(token, "encode_ip_hdr") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_IPHDR;
|
||||
else if (strcmp(token, "encode_tcp_stream") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
|
||||
else if (strcmp(token, "no_encode") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_NONE;
|
||||
else
|
||||
return -1;
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_PORT:
|
||||
strcpy(str_port, token);
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_SERVER:
|
||||
{
|
||||
int err;
|
||||
char *p;
|
||||
char s[sizeof(buffer)];
|
||||
|
||||
p = token;
|
||||
while (*p != ':' && *p != 0)
|
||||
p++;
|
||||
|
||||
if (*p != ':')
|
||||
{
|
||||
err = IpAddr(token, &server_addr);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p = ' ';
|
||||
|
||||
n = sscanf(token, "%s %s", s, str_server_port);
|
||||
if (n != 2)
|
||||
return -1;
|
||||
|
||||
err = IpAddr(s, &server_addr);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_RULE:
|
||||
n = sscanf(token, "%d", &rule_index);
|
||||
if (n != 1 || rule_index < 0)
|
||||
return -1;
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_DELETE:
|
||||
{
|
||||
int err;
|
||||
int rule_to_delete;
|
||||
|
||||
if (token_count != 2)
|
||||
return -1;
|
||||
|
||||
n = sscanf(token, "%d", &rule_to_delete);
|
||||
if (n != 1)
|
||||
return -1;
|
||||
err = RuleNumberDelete(rule_to_delete);
|
||||
if (err)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case STATE_READ_PROTO:
|
||||
if (strcmp(token, "tcp") == 0)
|
||||
proto = IPPROTO_TCP;
|
||||
else if (strcmp(token, "udp") == 0)
|
||||
proto = IPPROTO_UDP;
|
||||
else
|
||||
return -1;
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_SRC:
|
||||
case STATE_READ_DST:
|
||||
{
|
||||
int err;
|
||||
char *p;
|
||||
struct in_addr mask;
|
||||
struct in_addr addr;
|
||||
|
||||
p = token;
|
||||
while (*p != '/' && *p != 0)
|
||||
p++;
|
||||
|
||||
if (*p != '/')
|
||||
{
|
||||
IpMask(32, &mask);
|
||||
err = IpAddr(token, &addr);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int n;
|
||||
int nbits;
|
||||
char s[sizeof(buffer)];
|
||||
|
||||
*p = ' ';
|
||||
n = sscanf(token, "%s %d", s, &nbits);
|
||||
if (n != 2)
|
||||
return -1;
|
||||
|
||||
err = IpAddr(s, &addr);
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
err = IpMask(nbits, &mask);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (state == STATE_READ_SRC)
|
||||
{
|
||||
src_addr = addr;
|
||||
src_mask = mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_addr = addr;
|
||||
dst_mask = mask;
|
||||
}
|
||||
}
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
token = strtok(NULL, " \t");
|
||||
}
|
||||
#undef STATE_READ_KEYWORD
|
||||
#undef STATE_READ_TYPE
|
||||
#undef STATE_READ_PORT
|
||||
#undef STATE_READ_SERVER
|
||||
#undef STATE_READ_RULE
|
||||
#undef STATE_READ_DELETE
|
||||
#undef STATE_READ_PROTO
|
||||
#undef STATE_READ_SRC
|
||||
#undef STATE_READ_DST
|
||||
|
||||
/* Convert port strings to numbers. This needs to be done after
|
||||
the string is parsed, because the prototype might not be designated
|
||||
before the ports (which might be symbolic entries in /etc/services) */
|
||||
|
||||
if (strlen(str_port) != 0)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = IpPort(str_port, proto, &proxy_port);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy_port = 0;
|
||||
}
|
||||
|
||||
if (strlen(str_server_port) != 0)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = IpPort(str_server_port, proto, &server_port);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
server_port = 0;
|
||||
}
|
||||
|
||||
/* Check that at least the server address has been defined */
|
||||
if (server_addr.s_addr == 0)
|
||||
return -1;
|
||||
|
||||
/* Add to linked list */
|
||||
proxy_entry = malloc(sizeof(struct proxy_entry));
|
||||
if (proxy_entry == NULL)
|
||||
return -1;
|
||||
|
||||
proxy_entry->proxy_type = proxy_type;
|
||||
proxy_entry->rule_index = rule_index;
|
||||
proxy_entry->proto = proto;
|
||||
proxy_entry->proxy_port = htons(proxy_port);
|
||||
proxy_entry->server_port = htons(server_port);
|
||||
proxy_entry->server_addr = server_addr;
|
||||
proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr;
|
||||
proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr;
|
||||
proxy_entry->src_mask = src_mask;
|
||||
proxy_entry->dst_mask = dst_mask;
|
||||
|
||||
RuleAdd(proxy_entry);
|
||||
|
||||
return 0;
|
||||
}
|
@ -127,3 +127,8 @@ Version 2.5: December, 1997 (ee)
|
||||
|
||||
Version 2.6: May, 1998 (amurai)
|
||||
- Added supporting routine for NetBios over TCP/IP.
|
||||
|
||||
Version 3.0: January 1, 1999
|
||||
- Transparent proxying support added.
|
||||
- PPTP redirecting support added based on patches
|
||||
contributed by Dru Nelson <dnelson@redwoodsoft.com>.
|
||||
|
@ -1,11 +1,11 @@
|
||||
# $Id$
|
||||
# $Id: Makefile,v 1.9 1998/08/31 12:14:30 brian Exp $
|
||||
|
||||
LIB= alias
|
||||
SHLIB_MAJOR= 2
|
||||
SHLIB_MINOR= 5
|
||||
SHLIB_MAJOR= 3
|
||||
SHLIB_MINOR= 0
|
||||
CFLAGS+= -Wall -I${.CURDIR}
|
||||
SRCS= alias.c alias_cuseeme.c alias_db.c alias_ftp.c alias_irc.c \
|
||||
alias_nbt.c alias_old.c alias_util.c
|
||||
alias_nbt.c alias_proxy.c alias_util.c
|
||||
MAN3= libalias.3
|
||||
|
||||
beforeinstall:
|
||||
|
@ -93,6 +93,10 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#ifndef IPPROTO_GRE
|
||||
#define IPPROTO_GRE 47
|
||||
#endif
|
||||
|
||||
#include "alias_local.h"
|
||||
#include "alias.h"
|
||||
|
||||
@ -104,38 +108,13 @@
|
||||
#define IRC_CONTROL_PORT_NUMBER_2 6668
|
||||
#define CUSEEME_PORT_NUMBER 7648
|
||||
|
||||
/*
|
||||
The following macro is used to update an
|
||||
internet checksum. "delta" is a 32-bit
|
||||
accumulation of all the changes to the
|
||||
checksum (adding in new 16-bit words and
|
||||
subtracting out old words), and "cksum"
|
||||
is the checksum value to be updated.
|
||||
*/
|
||||
#define ADJUST_CHECKSUM(acc, cksum) { \
|
||||
acc += cksum; \
|
||||
if (acc < 0) \
|
||||
{ \
|
||||
acc = -acc; \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) ~acc; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) acc; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* TCP Handling Routines
|
||||
|
||||
TcpMonitorIn() -- These routines monitor TCP connections, and
|
||||
TcpMonitorOut() -- delete a link node when a connection is closed.
|
||||
TcpMonitorOut() delete a link when a connection is closed.
|
||||
|
||||
These routines look for SYN, ACK and RST flags to determine when TCP
|
||||
connections open and close. When a TCP connection closes, the data
|
||||
@ -406,7 +385,6 @@ fragment contained in ICMP data section */
|
||||
return(PKT_ALIAS_IGNORED);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
IcmpAliasIn3(struct ip *pip)
|
||||
{
|
||||
@ -429,6 +407,10 @@ IcmpAliasIn(struct ip *pip)
|
||||
int iresult;
|
||||
struct icmp *ic;
|
||||
|
||||
/* Return if proxy-only mode is enabled */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
iresult = PKT_ALIAS_IGNORED;
|
||||
@ -563,6 +545,10 @@ IcmpAliasOut(struct ip *pip)
|
||||
int iresult;
|
||||
struct icmp *ic;
|
||||
|
||||
/* Return if proxy-only mode is enabled */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
iresult = PKT_ALIAS_IGNORED;
|
||||
@ -588,12 +574,73 @@ IcmpAliasOut(struct ip *pip)
|
||||
return(iresult);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
PptpAliasIn(struct ip *pip)
|
||||
{
|
||||
/*
|
||||
Handle incoming PPTP packets. The
|
||||
only thing which is done in this case is to alias
|
||||
the dest IP address of the packet to our inside
|
||||
machine.
|
||||
*/
|
||||
struct in_addr alias_addr;
|
||||
|
||||
if (!GetPptpAlias (&alias_addr))
|
||||
return PKT_ALIAS_IGNORED;
|
||||
|
||||
if (pip->ip_src.s_addr != alias_addr.s_addr) {
|
||||
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
(u_short *) &alias_addr,
|
||||
(u_short *) &pip->ip_dst,
|
||||
2);
|
||||
pip->ip_dst = alias_addr;
|
||||
}
|
||||
|
||||
return PKT_ALIAS_OK;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
PptpAliasOut(struct ip *pip)
|
||||
{
|
||||
/*
|
||||
Handle outgoing PPTP packets. The
|
||||
only thing which is done in this case is to alias
|
||||
the source IP address of the packet.
|
||||
*/
|
||||
struct in_addr alias_addr;
|
||||
|
||||
if (!GetPptpAlias (&alias_addr))
|
||||
return PKT_ALIAS_IGNORED;
|
||||
|
||||
if (pip->ip_src.s_addr == alias_addr.s_addr) {
|
||||
|
||||
alias_addr = FindAliasAddress(pip->ip_src);
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
(u_short *) &alias_addr,
|
||||
(u_short *) &pip->ip_src,
|
||||
2);
|
||||
pip->ip_src = alias_addr;
|
||||
}
|
||||
|
||||
return PKT_ALIAS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
UdpAliasIn(struct ip *pip)
|
||||
{
|
||||
struct udphdr *ud;
|
||||
struct alias_link *link;
|
||||
|
||||
/* Return if proxy-only mode is enabled */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
|
||||
@ -670,6 +717,10 @@ UdpAliasOut(struct ip *pip)
|
||||
struct udphdr *ud;
|
||||
struct alias_link *link;
|
||||
|
||||
/* Return if proxy-only mode is enabled */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
|
||||
@ -751,14 +802,18 @@ TcpAliasIn(struct ip *pip)
|
||||
{
|
||||
struct in_addr alias_address;
|
||||
struct in_addr original_address;
|
||||
struct in_addr proxy_address;
|
||||
u_short alias_port;
|
||||
u_short proxy_port;
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
alias_address = GetAliasAddress(link);
|
||||
original_address = GetOriginalAddress(link);
|
||||
proxy_address = GetProxyAddress(link);
|
||||
alias_port = tc->th_dport;
|
||||
tc->th_dport = GetOriginalPort(link);
|
||||
proxy_port = GetProxyPort(link);
|
||||
|
||||
/* Adjust TCP checksum since destination port is being unaliased */
|
||||
/* and destination port is being altered. */
|
||||
@ -771,6 +826,22 @@ TcpAliasIn(struct ip *pip)
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
/* If this is a proxy, then modify the tcp source port and
|
||||
checksum accumulation */
|
||||
if (proxy_port != 0)
|
||||
{
|
||||
accumulate += tc->th_sport;
|
||||
tc->th_sport = proxy_port;
|
||||
accumulate -= tc->th_sport;
|
||||
|
||||
sptr = (u_short *) &pip->ip_src;
|
||||
accumulate += *sptr++;
|
||||
accumulate += *sptr;
|
||||
sptr = (u_short *) &proxy_address;
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
}
|
||||
|
||||
/* See if ack number needs to be modified */
|
||||
if (GetAckModified(link) == 1)
|
||||
{
|
||||
@ -792,11 +863,28 @@ TcpAliasIn(struct ip *pip)
|
||||
ADJUST_CHECKSUM(accumulate, tc->th_sum);
|
||||
|
||||
/* Restore original IP address */
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
(u_short *) &original_address,
|
||||
(u_short *) &pip->ip_dst,
|
||||
2);
|
||||
sptr = (u_short *) &pip->ip_dst;
|
||||
accumulate = *sptr++;
|
||||
accumulate += *sptr;
|
||||
pip->ip_dst = original_address;
|
||||
sptr = (u_short *) &pip->ip_dst;
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
/* If this is a transparent proxy packet, then modify the source
|
||||
address */
|
||||
if (proxy_address.s_addr != 0)
|
||||
{
|
||||
sptr = (u_short *) &pip->ip_src;
|
||||
accumulate += *sptr++;
|
||||
accumulate += *sptr;
|
||||
pip->ip_src = proxy_address;
|
||||
sptr = (u_short *) &pip->ip_src;
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
}
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
|
||||
/* Monitor TCP connection state */
|
||||
TcpMonitorIn(pip, link);
|
||||
@ -809,39 +897,94 @@ TcpAliasIn(struct ip *pip)
|
||||
static int
|
||||
TcpAliasOut(struct ip *pip, int maxpacketsize)
|
||||
{
|
||||
int proxy_type;
|
||||
u_short dest_port;
|
||||
u_short proxy_server_port;
|
||||
struct in_addr dest_address;
|
||||
struct in_addr proxy_server_address;
|
||||
struct tcphdr *tc;
|
||||
struct alias_link *link;
|
||||
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
|
||||
|
||||
if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
|
||||
return PKT_ALIAS_OK;
|
||||
|
||||
/* If this is a transparent proxy, save original destination,
|
||||
then alter the destination and adust checksums */
|
||||
dest_port = tc->th_dport;
|
||||
dest_address = pip->ip_dst;
|
||||
if (proxy_type != 0)
|
||||
{
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
accumulate = tc->th_dport;
|
||||
tc->th_dport = proxy_server_port;
|
||||
accumulate -= tc->th_dport;
|
||||
|
||||
sptr = (u_short *) &(pip->ip_dst);
|
||||
accumulate += *sptr++;
|
||||
accumulate += *sptr;
|
||||
sptr = (u_short *) &proxy_server_address;
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, tc->th_sum);
|
||||
|
||||
sptr = (u_short *) &(pip->ip_dst);
|
||||
accumulate = *sptr++;
|
||||
accumulate += *sptr;
|
||||
pip->ip_dst = proxy_server_address;
|
||||
sptr = (u_short *) &(pip->ip_dst);
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
}
|
||||
|
||||
link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
|
||||
tc->th_sport, tc->th_dport,
|
||||
IPPROTO_TCP);
|
||||
if (link !=NULL)
|
||||
{
|
||||
struct in_addr alias_address;
|
||||
u_short alias_port;
|
||||
struct in_addr alias_address;
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
/* Save original destination address, if this is a proxy packet.
|
||||
Also modify packet to include destination encoding. */
|
||||
if (proxy_type != 0)
|
||||
{
|
||||
SetProxyPort(link, dest_port);
|
||||
SetProxyAddress(link, dest_address);
|
||||
ProxyModify(link, pip, maxpacketsize, proxy_type);
|
||||
}
|
||||
|
||||
/* Get alias address and port */
|
||||
alias_port = GetAliasPort(link);
|
||||
alias_address = GetAliasAddress(link);
|
||||
|
||||
/* Monitor tcp connection state */
|
||||
TcpMonitorOut(pip, link);
|
||||
|
||||
/* Special processing for ftp connection */
|
||||
/* Special processing for IP encoding protocols */
|
||||
if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
|
||||
|| ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
|
||||
AliasHandleFtpOut(pip, link, maxpacketsize);
|
||||
if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
|
||||
|| ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
|
||||
|| ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
|
||||
AliasHandleIrcOut(pip, link, maxpacketsize);
|
||||
|
||||
/* Adjust TCP checksum since source port is being aliased */
|
||||
/* and source address is being altered */
|
||||
accumulate = tc->th_sport;
|
||||
accumulate -= alias_port;
|
||||
tc->th_sport = alias_port;
|
||||
accumulate -= tc->th_sport;
|
||||
|
||||
sptr = (u_short *) &(pip->ip_src);
|
||||
accumulate += *sptr++;
|
||||
accumulate += *sptr;
|
||||
@ -869,15 +1012,16 @@ TcpAliasOut(struct ip *pip, int maxpacketsize)
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, tc->th_sum)
|
||||
|
||||
/* Put alias address in TCP header */
|
||||
tc->th_sport = alias_port;
|
||||
|
||||
/* Change source address */
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
(u_short *) &alias_address,
|
||||
(u_short *) &pip->ip_src,
|
||||
2);
|
||||
sptr = (u_short *) &(pip->ip_src);
|
||||
accumulate = *sptr++;
|
||||
accumulate += *sptr;
|
||||
pip->ip_src = alias_address;
|
||||
sptr = (u_short *) &(pip->ip_src);
|
||||
accumulate -= *sptr++;
|
||||
accumulate -= *sptr;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum)
|
||||
|
||||
return(PKT_ALIAS_OK);
|
||||
}
|
||||
@ -1031,6 +1175,9 @@ PacketAliasIn(char *ptr, int maxpacketsize)
|
||||
struct ip *pip;
|
||||
int iresult;
|
||||
|
||||
if (packetAliasMode & PKT_ALIAS_REVERSE)
|
||||
return PacketAliasOut(ptr, maxpacketsize);
|
||||
|
||||
HouseKeeping();
|
||||
ClearCheckNewLink();
|
||||
pip = (struct ip *) ptr;
|
||||
@ -1055,6 +1202,9 @@ PacketAliasIn(char *ptr, int maxpacketsize)
|
||||
case IPPROTO_TCP:
|
||||
iresult = TcpAliasIn(pip);
|
||||
break;
|
||||
case IPPROTO_GRE:
|
||||
iresult = PptpAliasIn(pip);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ntohs(pip->ip_off) & IP_MF)
|
||||
@ -1097,8 +1247,6 @@ PacketAliasIn(char *ptr, int maxpacketsize)
|
||||
#define UNREG_ADDR_C_LOWER 0xc0a80000
|
||||
#define UNREG_ADDR_C_UPPER 0xc0a8ffff
|
||||
|
||||
|
||||
|
||||
int
|
||||
PacketAliasOut(char *ptr, /* valid IP packet */
|
||||
int maxpacketsize /* How much the packet data may grow
|
||||
@ -1109,6 +1257,9 @@ PacketAliasOut(char *ptr, /* valid IP packet */
|
||||
struct in_addr addr_save;
|
||||
struct ip *pip;
|
||||
|
||||
if (packetAliasMode & PKT_ALIAS_REVERSE)
|
||||
return PacketAliasIn(ptr, maxpacketsize);
|
||||
|
||||
HouseKeeping();
|
||||
ClearCheckNewLink();
|
||||
pip = (struct ip *) ptr;
|
||||
@ -1153,6 +1304,9 @@ PacketAliasOut(char *ptr, /* valid IP packet */
|
||||
case IPPROTO_TCP:
|
||||
iresult = TcpAliasOut(pip, maxpacketsize);
|
||||
break;
|
||||
case IPPROTO_GRE:
|
||||
iresult = PptpAliasOut(pip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -7,7 +7,7 @@
|
||||
This software is placed into the public domain with no restrictions
|
||||
on its distribution.
|
||||
|
||||
$Id: alias.h,v 1.7 1998/01/16 12:56:07 bde Exp $
|
||||
$Id: alias.h,v 1.8 1998/04/19 21:42:05 brian Exp $
|
||||
*/
|
||||
|
||||
|
||||
@ -55,6 +55,10 @@ struct alias_link;
|
||||
struct in_addr, u_short,
|
||||
u_char);
|
||||
|
||||
extern int
|
||||
PacketAliasPptp(struct in_addr);
|
||||
|
||||
|
||||
extern struct alias_link *
|
||||
PacketAliasRedirectAddr(struct in_addr,
|
||||
struct in_addr);
|
||||
@ -82,28 +86,10 @@ struct alias_link;
|
||||
extern u_short
|
||||
PacketAliasInternetChecksum(u_short *, int);
|
||||
|
||||
/* Transparent Proxying */
|
||||
extern int
|
||||
PacketAliasProxyRule(char *);
|
||||
|
||||
/*
|
||||
In version 2.2, the function names were rationalized
|
||||
to all be of the form PacketAlias... These are the
|
||||
old function names for backwards compatibility
|
||||
*/
|
||||
extern int SaveFragmentPtr(char *);
|
||||
extern char *GetNextFragmentPtr(char *);
|
||||
extern void FragmentAliasIn(char *, char *);
|
||||
extern void SetPacketAliasAddress(struct in_addr);
|
||||
extern void InitPacketAlias(void);
|
||||
extern unsigned int SetPacketAliasMode(unsigned int, unsigned int);
|
||||
extern int PacketAliasIn2(char *, struct in_addr, int maxpacketsize);
|
||||
extern int PacketAliasOut2(char *, struct in_addr, int maxpacketsize);
|
||||
extern int
|
||||
PacketAliasPermanentLink(struct in_addr, u_short,
|
||||
struct in_addr, u_short,
|
||||
u_short, u_char);
|
||||
extern u_short InternetChecksum(u_short *, int);
|
||||
|
||||
/* Obsolete constant */
|
||||
#define PKT_ALIAS_NEW_LINK 5
|
||||
|
||||
/********************** Mode flags ********************/
|
||||
/* Set these flags using SetPacketAliasMode() */
|
||||
@ -138,7 +124,6 @@ extern u_short InternetChecksum(u_short *, int);
|
||||
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 */
|
||||
@ -162,6 +147,14 @@ extern u_short InternetChecksum(u_short *, int);
|
||||
#define PKT_ALIAS_PUNCH_FW 0x40
|
||||
#endif
|
||||
|
||||
/* If PKT_ALIAS_PROXY_ONLY is set, then NAT will be disabled and only
|
||||
transparent proxying performed */
|
||||
#define PKT_ALIAS_PROXY_ONLY 0x40
|
||||
|
||||
/* If PKT_ALIAS_REVERSE is set, the actions of PacketAliasIn()
|
||||
and PacketAliasOut() are reversed */
|
||||
#define PKT_ALIAS_REVERSE 0x80
|
||||
|
||||
/* Return Codes */
|
||||
#define PKT_ALIAS_ERROR -1
|
||||
#define PKT_ALIAS_OK 1
|
||||
|
@ -56,12 +56,12 @@
|
||||
Added ability to create an alias port without
|
||||
either destination address or port specified.
|
||||
port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
|
||||
|
||||
|
||||
Removed K&R style function headers
|
||||
and general cleanup. (ee)
|
||||
|
||||
Added packetAliasMode to replace compiler #defines's (ee)
|
||||
|
||||
|
||||
Allocates sockets for partially specified
|
||||
ports if ALIAS_USE_SOCKETS defined. (cjm)
|
||||
|
||||
@ -73,10 +73,10 @@
|
||||
links. (J. Fortes suggested the need for this.)
|
||||
Examples:
|
||||
|
||||
(192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
|
||||
(192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
|
||||
|
||||
(192.168.0.2, port 21) <-> alias port 3604, known dest addr
|
||||
unknown dest port
|
||||
unknown dest port
|
||||
|
||||
These permament links allow for incoming connections to
|
||||
machines on the local network. They can be given with a
|
||||
@ -111,7 +111,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
@ -139,7 +139,7 @@
|
||||
#define LINK_TABLE_IN_SIZE 4001
|
||||
|
||||
/* Parameters used for cleanup of expired links */
|
||||
#define ALIAS_CLEANUP_INTERVAL_SECS 60
|
||||
#define ALIAS_CLEANUP_INTERVAL_SECS 60
|
||||
#define ALIAS_CLEANUP_MAX_SPOKES 30
|
||||
|
||||
/* Timouts (in seconds) for different link types) */
|
||||
@ -174,14 +174,14 @@
|
||||
|
||||
/* Dummy port number codes used for FindLinkIn/Out() and AddLink().
|
||||
These constants can be anything except zero, which indicates an
|
||||
unknown port numbea. */
|
||||
unknown port number. */
|
||||
|
||||
#define NO_DEST_PORT 1
|
||||
#define NO_SRC_PORT 1
|
||||
|
||||
|
||||
|
||||
/* Data Structures
|
||||
/* Data Structures
|
||||
|
||||
The fundamental data structure used in this program is
|
||||
"struct alias_link". Whenever a TCP connection is made,
|
||||
@ -237,11 +237,13 @@ struct tcp_dat
|
||||
struct alias_link /* Main data structure */
|
||||
{
|
||||
struct in_addr src_addr; /* Address and port information */
|
||||
struct in_addr dst_addr; /* . */
|
||||
struct in_addr alias_addr; /* . */
|
||||
u_short src_port; /* . */
|
||||
u_short dst_port; /* . */
|
||||
u_short alias_port; /* . */
|
||||
struct in_addr dst_addr;
|
||||
struct in_addr alias_addr;
|
||||
struct in_addr proxy_addr;
|
||||
u_short src_port;
|
||||
u_short dst_port;
|
||||
u_short alias_port;
|
||||
u_short proxy_port;
|
||||
|
||||
int link_type; /* Type of link: tcp, udp, icmp, frag */
|
||||
|
||||
@ -348,6 +350,12 @@ static int fireWallFD = -1; /* File descriptor to be able to */
|
||||
/* flag. */
|
||||
#endif
|
||||
|
||||
static int pptpAliasFlag; /* Indicates if PPTP aliasing is */
|
||||
/* on or off */
|
||||
static struct in_addr pptpAliasAddr; /* Address of source of PPTP */
|
||||
/* packets. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -853,15 +861,17 @@ AddLink(struct in_addr src_addr,
|
||||
alias_addr.s_addr = 0;
|
||||
|
||||
/* Basic initialization */
|
||||
link->src_addr = src_addr;
|
||||
link->dst_addr = dst_addr;
|
||||
link->src_port = src_port;
|
||||
link->alias_addr = alias_addr;
|
||||
link->dst_port = dst_port;
|
||||
link->link_type = link_type;
|
||||
link->sockfd = -1;
|
||||
link->flags = 0;
|
||||
link->timestamp = timeStamp;
|
||||
link->src_addr = src_addr;
|
||||
link->dst_addr = dst_addr;
|
||||
link->alias_addr = alias_addr;
|
||||
link->proxy_addr.s_addr = 0;
|
||||
link->src_port = src_port;
|
||||
link->dst_port = dst_port;
|
||||
link->proxy_port = 0;
|
||||
link->link_type = link_type;
|
||||
link->sockfd = -1;
|
||||
link->flags = 0;
|
||||
link->timestamp = timeStamp;
|
||||
|
||||
/* Expiration time */
|
||||
switch (link_type)
|
||||
@ -1304,7 +1314,9 @@ FindUdpTcpIn(struct in_addr dst_addr,
|
||||
dst_port, alias_port,
|
||||
link_type, 1);
|
||||
|
||||
if ( !(packetAliasMode & PKT_ALIAS_DENY_INCOMING) && link == NULL)
|
||||
if (!(packetAliasMode & PKT_ALIAS_DENY_INCOMING)
|
||||
&& !(packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
&& link == NULL)
|
||||
{
|
||||
struct in_addr target_addr;
|
||||
|
||||
@ -1578,6 +1590,34 @@ SetAckModified(struct alias_link *link)
|
||||
}
|
||||
|
||||
|
||||
struct in_addr
|
||||
GetProxyAddress(struct alias_link *link)
|
||||
{
|
||||
return link->proxy_addr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SetProxyAddress(struct alias_link *link, struct in_addr addr)
|
||||
{
|
||||
link->proxy_addr = addr;
|
||||
}
|
||||
|
||||
|
||||
u_short
|
||||
GetProxyPort(struct alias_link *link)
|
||||
{
|
||||
return link->proxy_port;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SetProxyPort(struct alias_link *link, u_short port)
|
||||
{
|
||||
link->proxy_port = port;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
GetAckModified(struct alias_link *link)
|
||||
{
|
||||
@ -1906,6 +1946,26 @@ PacketAliasRedirectPort(struct in_addr src_addr, u_short src_port,
|
||||
return link;
|
||||
}
|
||||
|
||||
/* Translate PPTP packets to a machine on the inside
|
||||
*/
|
||||
int
|
||||
PacketAliasPptp(struct in_addr src_addr)
|
||||
{
|
||||
|
||||
pptpAliasAddr = src_addr; /* Address of the inside PPTP machine */
|
||||
pptpAliasFlag = 1;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetPptpAlias (struct in_addr* alias_addr)
|
||||
{
|
||||
if (pptpAliasFlag)
|
||||
*alias_addr = pptpAliasAddr;
|
||||
|
||||
return pptpAliasFlag;
|
||||
}
|
||||
|
||||
/* Static address translation */
|
||||
struct alias_link *
|
||||
@ -2007,6 +2067,8 @@ PacketAliasInit(void)
|
||||
packetAliasMode = PKT_ALIAS_SAME_PORTS
|
||||
| PKT_ALIAS_USE_SOCKETS
|
||||
| PKT_ALIAS_RESET_ON_ADDR_CHANGE;
|
||||
|
||||
pptpAliasFlag = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,9 +1,11 @@
|
||||
/* -*- 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
|
||||
as any future add-ons). It also includes macros, globals and
|
||||
struct definitions shared by more than one alias*.c file.
|
||||
|
||||
This include file 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.
|
||||
@ -15,9 +17,54 @@
|
||||
#ifndef ALIAS_LOCAL_H
|
||||
#define ALIAS_LOCAL_H
|
||||
|
||||
|
||||
/*
|
||||
Macros
|
||||
*/
|
||||
|
||||
/*
|
||||
The following macro is used to update an
|
||||
internet checksum. "delta" is a 32-bit
|
||||
accumulation of all the changes to the
|
||||
checksum (adding in new 16-bit words and
|
||||
subtracting out old words), and "cksum"
|
||||
is the checksum value to be updated.
|
||||
*/
|
||||
#define ADJUST_CHECKSUM(acc, cksum) { \
|
||||
acc += cksum; \
|
||||
if (acc < 0) \
|
||||
{ \
|
||||
acc = -acc; \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) ~acc; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) acc; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Globals
|
||||
*/
|
||||
|
||||
extern int packetAliasMode;
|
||||
|
||||
struct alias_link;
|
||||
|
||||
/*
|
||||
Structs
|
||||
*/
|
||||
|
||||
struct alias_link; /* Incomplete structure */
|
||||
|
||||
|
||||
/*
|
||||
Prototypes
|
||||
*/
|
||||
|
||||
/* General utilities */
|
||||
u_short IpChecksum(struct ip *);
|
||||
@ -71,6 +118,10 @@ struct in_addr GetDefaultAliasAddress(void);
|
||||
void SetDefaultAliasAddress(struct in_addr);
|
||||
u_short GetOriginalPort(struct alias_link *);
|
||||
u_short GetAliasPort(struct alias_link *);
|
||||
struct in_addr GetProxyAddress(struct alias_link *);
|
||||
void SetProxyAddress(struct alias_link *, struct in_addr);
|
||||
u_short GetProxyPort(struct alias_link *);
|
||||
void SetProxyPort(struct alias_link *, u_short);
|
||||
void SetAckModified(struct alias_link *);
|
||||
int GetAckModified(struct alias_link *);
|
||||
int GetDeltaAckIn(struct ip *, struct alias_link *);
|
||||
@ -88,13 +139,24 @@ void HouseKeeping(void);
|
||||
|
||||
/* Tcp specfic routines */
|
||||
/*lint -save -library Suppress flexelint warnings */
|
||||
|
||||
/* FTP routines */
|
||||
void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
|
||||
|
||||
/* IRC routines */
|
||||
void AliasHandleIrcOut(struct ip *pip, struct alias_link *link, int maxsize );
|
||||
|
||||
/* NetBIOS routines */
|
||||
int AliasHandleUdpNbt(struct ip *, struct alias_link *, struct in_addr *, u_short);
|
||||
int AliasHandleUdpNbtNS(struct ip *, struct alias_link *, struct in_addr *, u_short *, struct in_addr *, u_short *);
|
||||
|
||||
/* CUSeeMe routines */
|
||||
void AliasHandleCUSeeMeOut(struct ip *, struct alias_link *);
|
||||
void AliasHandleCUSeeMeIn(struct ip *, struct in_addr);
|
||||
|
||||
/* Transparent proxy routines */
|
||||
int ProxyCheck(struct ip *, struct in_addr *, u_short *);
|
||||
void ProxyModify(struct alias_link *, struct ip *, int, int);
|
||||
|
||||
|
||||
enum alias_tcp_state {
|
||||
@ -103,5 +165,6 @@ enum alias_tcp_state {
|
||||
ALIAS_TCP_STATE_DISCONNECTED
|
||||
};
|
||||
|
||||
int GetPptpAlias (struct in_addr*);
|
||||
/*lint -restore */
|
||||
#endif /* defined(ALIAS_LOCAL_H) */
|
||||
|
801
sys/netinet/libalias/alias_proxy.c
Normal file
801
sys/netinet/libalias/alias_proxy.c
Normal file
@ -0,0 +1,801 @@
|
||||
/* file: alias_proxy.c
|
||||
|
||||
This file encapsulates special operations related to transparent
|
||||
proxy redirection. This is where packets with a particular destination,
|
||||
usually tcp port 80, are redirected to a proxy server.
|
||||
|
||||
When packets are proxied, the destination address and port are
|
||||
modified. In certain cases, it is necessary to somehow encode
|
||||
the original address/port info into the packet. Two methods are
|
||||
presently supported: addition of a [DEST addr port] string at the
|
||||
beginning a of tcp stream, or inclusion of an optional field
|
||||
in the IP header.
|
||||
|
||||
There is one public API function:
|
||||
|
||||
PacketAliasProxyRule() -- Adds and deletes proxy
|
||||
rules.
|
||||
|
||||
Rules are stored in a linear linked list, so lookup efficiency
|
||||
won't be too good for large lists.
|
||||
|
||||
|
||||
Initial development: April, 1998 (cjm)
|
||||
*/
|
||||
|
||||
|
||||
/* System includes */
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/* BSD IPV4 includes */
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "alias_local.h" /* Functions used by alias*.c */
|
||||
#include "alias.h" /* Public API functions for libalias */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Data structures
|
||||
*/
|
||||
|
||||
/*
|
||||
* A linked list of arbitrary length, based on struct proxy_entry is
|
||||
* used to store proxy rules.
|
||||
*/
|
||||
struct proxy_entry
|
||||
{
|
||||
#define PROXY_TYPE_ENCODE_NONE 1
|
||||
#define PROXY_TYPE_ENCODE_TCPSTREAM 2
|
||||
#define PROXY_TYPE_ENCODE_IPHDR 3
|
||||
int rule_index;
|
||||
int proxy_type;
|
||||
u_char proto;
|
||||
u_short proxy_port;
|
||||
u_short server_port;
|
||||
|
||||
struct in_addr server_addr;
|
||||
|
||||
struct in_addr src_addr;
|
||||
struct in_addr src_mask;
|
||||
|
||||
struct in_addr dst_addr;
|
||||
struct in_addr dst_mask;
|
||||
|
||||
struct proxy_entry *next;
|
||||
struct proxy_entry *last;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
File scope variables
|
||||
*/
|
||||
|
||||
static struct proxy_entry *proxyList;
|
||||
|
||||
|
||||
|
||||
/* Local (static) functions:
|
||||
|
||||
IpMask() -- Utility function for creating IP
|
||||
masks from integer (1-32) specification.
|
||||
IpAddr() -- Utility function for converting string
|
||||
to IP address
|
||||
IpPort() -- Utility function for converting string
|
||||
to port number
|
||||
RuleAdd() -- Adds an element to the rule list.
|
||||
RuleDelete() -- Removes an element from the rule list.
|
||||
RuleNumberDelete() -- Removes all elements from the rule list
|
||||
having a certain rule number.
|
||||
ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning
|
||||
of a TCP stream.
|
||||
ProxyEncodeIpHeader() -- Adds an IP option indicating the true
|
||||
destination of a proxied IP packet
|
||||
*/
|
||||
|
||||
static int IpMask(int, struct in_addr *);
|
||||
static int IpAddr(char *, struct in_addr *);
|
||||
static int IpPort(char *, int, int *);
|
||||
static void RuleAdd(struct proxy_entry *);
|
||||
static void RuleDelete(struct proxy_entry *);
|
||||
static int RuleNumberDelete(int);
|
||||
static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int);
|
||||
static void ProxyEncodeIpHeader(struct ip *, int);
|
||||
|
||||
static int
|
||||
IpMask(int nbits, struct in_addr *mask)
|
||||
{
|
||||
int i;
|
||||
u_int imask;
|
||||
|
||||
if (nbits < 0 || nbits > 32)
|
||||
return -1;
|
||||
|
||||
imask = 0;
|
||||
for (i=0; i<nbits; i++)
|
||||
imask = (imask >> 1) + 0x80000000;
|
||||
mask->s_addr = htonl(imask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
IpAddr(char *s, struct in_addr *addr)
|
||||
{
|
||||
if (inet_aton(s, addr) == 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
IpPort(char *s, int proto, int *port)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = sscanf(s, "%d", port);
|
||||
if (n != 1)
|
||||
{
|
||||
struct servent *se;
|
||||
|
||||
if (proto == IPPROTO_TCP)
|
||||
se = getservbyname(s, "tcp");
|
||||
else if (proto == IPPROTO_UDP)
|
||||
se = getservbyname(s, "udp");
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (se == NULL)
|
||||
return -1;
|
||||
|
||||
*port = (u_int) ntohs(se->s_port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
RuleAdd(struct proxy_entry *entry)
|
||||
{
|
||||
int rule_index;
|
||||
struct proxy_entry *ptr;
|
||||
struct proxy_entry *ptr_last;
|
||||
|
||||
if (proxyList == NULL)
|
||||
{
|
||||
proxyList = entry;
|
||||
entry->last = NULL;
|
||||
entry->next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
rule_index = entry->rule_index;
|
||||
ptr = proxyList;
|
||||
ptr_last = NULL;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
if (ptr->rule_index >= rule_index)
|
||||
{
|
||||
if (ptr_last == NULL)
|
||||
{
|
||||
entry->next = proxyList;
|
||||
entry->last = NULL;
|
||||
proxyList->last = entry;
|
||||
proxyList = entry;
|
||||
return;
|
||||
}
|
||||
|
||||
ptr_last->next = entry;
|
||||
ptr->last = entry;
|
||||
entry->last = ptr->last;
|
||||
entry->next = ptr;
|
||||
return;
|
||||
}
|
||||
ptr_last = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
ptr_last->next = entry;
|
||||
entry->last = ptr_last;
|
||||
entry->next = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
RuleDelete(struct proxy_entry *entry)
|
||||
{
|
||||
if (entry->last != NULL)
|
||||
entry->last->next = entry->next;
|
||||
else
|
||||
proxyList = entry->next;
|
||||
|
||||
if (entry->next != NULL)
|
||||
entry->next->last = entry->last;
|
||||
|
||||
free(entry);
|
||||
}
|
||||
|
||||
static int
|
||||
RuleNumberDelete(int rule_index)
|
||||
{
|
||||
int err;
|
||||
struct proxy_entry *ptr;
|
||||
|
||||
err = -1;
|
||||
ptr = proxyList;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
struct proxy_entry *ptr_next;
|
||||
|
||||
ptr_next = ptr->next;
|
||||
if (ptr->rule_index == rule_index)
|
||||
{
|
||||
err = 0;
|
||||
RuleDelete(ptr);
|
||||
}
|
||||
|
||||
ptr = ptr_next;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
ProxyEncodeTcpStream(struct alias_link *link,
|
||||
struct ip *pip,
|
||||
int maxpacketsize)
|
||||
{
|
||||
int slen;
|
||||
char buffer[40];
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Compute pointer to tcp header */
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
|
||||
/* Don't modify if once already modified */
|
||||
|
||||
if (GetAckModified (link))
|
||||
return;
|
||||
|
||||
/* Translate destination address and port to string form */
|
||||
snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]",
|
||||
inet_ntoa(GetProxyAddress (link)), (u_int) ntohs(GetProxyPort (link)));
|
||||
|
||||
/* Pad string out to a multiple of two in length */
|
||||
slen = strlen(buffer);
|
||||
switch (slen % 2)
|
||||
{
|
||||
case 0:
|
||||
strcat(buffer, " \n");
|
||||
slen += 2;
|
||||
break;
|
||||
case 1:
|
||||
strcat(buffer, "\n");
|
||||
slen += 1;
|
||||
}
|
||||
|
||||
/* Check for packet overflow */
|
||||
if ((ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize)
|
||||
return;
|
||||
|
||||
/* Shift existing TCP data and insert destination string */
|
||||
{
|
||||
int dlen;
|
||||
int hlen;
|
||||
u_char *p;
|
||||
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
dlen = ntohs (pip->ip_len) - hlen;
|
||||
|
||||
/* Modify first packet that has data in it */
|
||||
|
||||
if (dlen == 0)
|
||||
return;
|
||||
|
||||
p = (char *) pip;
|
||||
p += hlen;
|
||||
|
||||
memmove(p + slen, p, dlen);
|
||||
memcpy(p, buffer, slen);
|
||||
}
|
||||
|
||||
/* Save information about modfied sequence number */
|
||||
{
|
||||
int delta;
|
||||
|
||||
SetAckModified(link);
|
||||
delta = GetDeltaSeqOut(pip, link);
|
||||
AddSeq(pip, link, delta+slen);
|
||||
}
|
||||
|
||||
/* Update IP header packet length and checksum */
|
||||
{
|
||||
int accumulate;
|
||||
|
||||
accumulate = pip->ip_len;
|
||||
pip->ip_len = htons(ntohs(pip->ip_len) + slen);
|
||||
accumulate -= pip->ip_len;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
}
|
||||
|
||||
/* Update TCP checksum, Use TcpChecksum since so many things have
|
||||
already changed. */
|
||||
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum (pip);
|
||||
}
|
||||
|
||||
static void
|
||||
ProxyEncodeIpHeader(struct ip *pip,
|
||||
int maxpacketsize)
|
||||
{
|
||||
#define OPTION_LEN_BYTES 8
|
||||
#define OPTION_LEN_INT16 4
|
||||
#define OPTION_LEN_INT32 2
|
||||
u_char option[OPTION_LEN_BYTES];
|
||||
|
||||
fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip));
|
||||
fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip));
|
||||
|
||||
/* Check to see that there is room to add an IP option */
|
||||
if (pip->ip_hl > (0x0f - OPTION_LEN_INT32))
|
||||
return;
|
||||
|
||||
/* Build option and copy into packet */
|
||||
{
|
||||
u_char *ptr;
|
||||
struct tcphdr *tc;
|
||||
|
||||
ptr = (u_char *) pip;
|
||||
ptr += 20;
|
||||
memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20);
|
||||
|
||||
option[0] = 0x64; /* class: 3 (reserved), option 4 */
|
||||
option[1] = OPTION_LEN_BYTES;
|
||||
|
||||
memcpy(&option[2], (u_char *) &pip->ip_dst, 4);
|
||||
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
memcpy(&option[6], (u_char *) &tc->th_sport, 2);
|
||||
|
||||
memcpy(ptr, option, 8);
|
||||
}
|
||||
|
||||
/* Update checksum, header length and packet length */
|
||||
{
|
||||
int i;
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
sptr = (u_short *) option;
|
||||
accumulate = 0;
|
||||
for (i=0; i<OPTION_LEN_INT16; i++)
|
||||
accumulate -= *(sptr++);
|
||||
|
||||
sptr = (u_short *) pip;
|
||||
accumulate += *sptr;
|
||||
pip->ip_hl += OPTION_LEN_INT32;
|
||||
accumulate -= *sptr;
|
||||
|
||||
accumulate += pip->ip_len;
|
||||
pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES);
|
||||
accumulate -= pip->ip_len;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
}
|
||||
#undef OPTION_LEN_BYTES
|
||||
#undef OPTION_LEN_INT16
|
||||
#undef OPTION_LEN_INT32
|
||||
fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip));
|
||||
fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip));
|
||||
}
|
||||
|
||||
|
||||
/* Functions by other packet alias source files
|
||||
|
||||
ProxyCheck() -- Checks whether an outgoing packet should
|
||||
be proxied.
|
||||
ProxyModify() -- Encodes the original destination address/port
|
||||
for a packet which is to be redirected to
|
||||
a proxy server.
|
||||
*/
|
||||
|
||||
int
|
||||
ProxyCheck(struct ip *pip,
|
||||
struct in_addr *proxy_server_addr,
|
||||
u_short *proxy_server_port)
|
||||
{
|
||||
u_short dst_port;
|
||||
struct in_addr src_addr;
|
||||
struct in_addr dst_addr;
|
||||
struct proxy_entry *ptr;
|
||||
|
||||
src_addr = pip->ip_src;
|
||||
dst_addr = pip->ip_dst;
|
||||
dst_port = ((struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)))
|
||||
->th_dport;
|
||||
|
||||
ptr = proxyList;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
u_short proxy_port;
|
||||
|
||||
proxy_port = ptr->proxy_port;
|
||||
if ((dst_port == proxy_port || proxy_port == 0)
|
||||
&& pip->ip_p == ptr->proto
|
||||
&& src_addr.s_addr != ptr->server_addr.s_addr)
|
||||
{
|
||||
struct in_addr src_addr_masked;
|
||||
struct in_addr dst_addr_masked;
|
||||
|
||||
src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr;
|
||||
dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr;
|
||||
|
||||
if ((src_addr_masked.s_addr == ptr->src_addr.s_addr)
|
||||
&& (dst_addr_masked.s_addr == ptr->dst_addr.s_addr))
|
||||
{
|
||||
if ((*proxy_server_port = ptr->server_port) == 0)
|
||||
*proxy_server_port = dst_port;
|
||||
*proxy_server_addr = ptr->server_addr;
|
||||
return ptr->proxy_type;
|
||||
}
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ProxyModify(struct alias_link *link,
|
||||
struct ip *pip,
|
||||
int maxpacketsize,
|
||||
int proxy_type)
|
||||
{
|
||||
switch (proxy_type)
|
||||
{
|
||||
case PROXY_TYPE_ENCODE_IPHDR:
|
||||
ProxyEncodeIpHeader(pip, maxpacketsize);
|
||||
break;
|
||||
|
||||
case PROXY_TYPE_ENCODE_TCPSTREAM:
|
||||
ProxyEncodeTcpStream(link, pip, maxpacketsize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Public API functions
|
||||
*/
|
||||
|
||||
int
|
||||
PacketAliasProxyRule(char *cmd)
|
||||
{
|
||||
/*
|
||||
* This function takes command strings of the form:
|
||||
*
|
||||
* server <addr>[:<port>]
|
||||
* [port <port>]
|
||||
* [rule n]
|
||||
* [proto tcp|udp]
|
||||
* [src <addr>[/n]]
|
||||
* [dst <addr>[/n]]
|
||||
* [type encode_tcp_stream|encode_ip_hdr|no_encode]
|
||||
*
|
||||
* delete <rule number>
|
||||
*
|
||||
* Subfields can be in arbitrary order. Port numbers and addresses
|
||||
* must be in either numeric or symbolic form. An optional rule number
|
||||
* is used to control the order in which rules are searched. If two
|
||||
* rules have the same number, then search order cannot be guaranteed,
|
||||
* and the rules should be disjoint. If no rule number is specified,
|
||||
* then 0 is used, and group 0 rules are always checked before any
|
||||
* others.
|
||||
*/
|
||||
int i, n, len;
|
||||
int cmd_len;
|
||||
int token_count;
|
||||
int state;
|
||||
char *token;
|
||||
char buffer[256];
|
||||
char str_port[sizeof(buffer)];
|
||||
char str_server_port[sizeof(buffer)];
|
||||
|
||||
int rule_index;
|
||||
int proto;
|
||||
int proxy_type;
|
||||
int proxy_port;
|
||||
int server_port;
|
||||
struct in_addr server_addr;
|
||||
struct in_addr src_addr, src_mask;
|
||||
struct in_addr dst_addr, dst_mask;
|
||||
struct proxy_entry *proxy_entry;
|
||||
|
||||
/* Copy command line into a buffer */
|
||||
cmd_len = strlen(cmd);
|
||||
if (cmd_len > (sizeof(buffer) - 1))
|
||||
return -1;
|
||||
strcpy(buffer, cmd);
|
||||
|
||||
/* Convert to lower case */
|
||||
len = strlen(buffer);
|
||||
for (i=0; i<len; i++)
|
||||
buffer[i] = tolower(buffer[i]);
|
||||
|
||||
/* Set default proxy type */
|
||||
|
||||
/* Set up default values */
|
||||
rule_index = 0;
|
||||
proxy_type = PROXY_TYPE_ENCODE_NONE;
|
||||
proto = IPPROTO_TCP;
|
||||
proxy_port = 0;
|
||||
server_addr.s_addr = 0;
|
||||
server_port = 0;
|
||||
src_addr.s_addr = 0;
|
||||
IpMask(0, &src_mask);
|
||||
dst_addr.s_addr = 0;
|
||||
IpMask(0, &dst_mask);
|
||||
|
||||
str_port[0] = 0;
|
||||
str_server_port[0] = 0;
|
||||
|
||||
/* Parse command string with state machine */
|
||||
#define STATE_READ_KEYWORD 0
|
||||
#define STATE_READ_TYPE 1
|
||||
#define STATE_READ_PORT 2
|
||||
#define STATE_READ_SERVER 3
|
||||
#define STATE_READ_RULE 4
|
||||
#define STATE_READ_DELETE 5
|
||||
#define STATE_READ_PROTO 6
|
||||
#define STATE_READ_SRC 7
|
||||
#define STATE_READ_DST 8
|
||||
state = STATE_READ_KEYWORD;
|
||||
token = strtok(buffer, " \t");
|
||||
token_count = 0;
|
||||
while (token != NULL)
|
||||
{
|
||||
token_count++;
|
||||
switch (state)
|
||||
{
|
||||
case STATE_READ_KEYWORD:
|
||||
if (strcmp(token, "type") == 0)
|
||||
state = STATE_READ_TYPE;
|
||||
else if (strcmp(token, "port") == 0)
|
||||
state = STATE_READ_PORT;
|
||||
else if (strcmp(token, "server") == 0)
|
||||
state = STATE_READ_SERVER;
|
||||
else if (strcmp(token, "rule") == 0)
|
||||
state = STATE_READ_RULE;
|
||||
else if (strcmp(token, "delete") == 0)
|
||||
state = STATE_READ_DELETE;
|
||||
else if (strcmp(token, "proto") == 0)
|
||||
state = STATE_READ_PROTO;
|
||||
else if (strcmp(token, "src") == 0)
|
||||
state = STATE_READ_SRC;
|
||||
else if (strcmp(token, "dst") == 0)
|
||||
state = STATE_READ_DST;
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case STATE_READ_TYPE:
|
||||
if (strcmp(token, "encode_ip_hdr") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_IPHDR;
|
||||
else if (strcmp(token, "encode_tcp_stream") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
|
||||
else if (strcmp(token, "no_encode") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_NONE;
|
||||
else
|
||||
return -1;
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_PORT:
|
||||
strcpy(str_port, token);
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_SERVER:
|
||||
{
|
||||
int err;
|
||||
char *p;
|
||||
char s[sizeof(buffer)];
|
||||
|
||||
p = token;
|
||||
while (*p != ':' && *p != 0)
|
||||
p++;
|
||||
|
||||
if (*p != ':')
|
||||
{
|
||||
err = IpAddr(token, &server_addr);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p = ' ';
|
||||
|
||||
n = sscanf(token, "%s %s", s, str_server_port);
|
||||
if (n != 2)
|
||||
return -1;
|
||||
|
||||
err = IpAddr(s, &server_addr);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_RULE:
|
||||
n = sscanf(token, "%d", &rule_index);
|
||||
if (n != 1 || rule_index < 0)
|
||||
return -1;
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_DELETE:
|
||||
{
|
||||
int err;
|
||||
int rule_to_delete;
|
||||
|
||||
if (token_count != 2)
|
||||
return -1;
|
||||
|
||||
n = sscanf(token, "%d", &rule_to_delete);
|
||||
if (n != 1)
|
||||
return -1;
|
||||
err = RuleNumberDelete(rule_to_delete);
|
||||
if (err)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case STATE_READ_PROTO:
|
||||
if (strcmp(token, "tcp") == 0)
|
||||
proto = IPPROTO_TCP;
|
||||
else if (strcmp(token, "udp") == 0)
|
||||
proto = IPPROTO_UDP;
|
||||
else
|
||||
return -1;
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_SRC:
|
||||
case STATE_READ_DST:
|
||||
{
|
||||
int err;
|
||||
char *p;
|
||||
struct in_addr mask;
|
||||
struct in_addr addr;
|
||||
|
||||
p = token;
|
||||
while (*p != '/' && *p != 0)
|
||||
p++;
|
||||
|
||||
if (*p != '/')
|
||||
{
|
||||
IpMask(32, &mask);
|
||||
err = IpAddr(token, &addr);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int n;
|
||||
int nbits;
|
||||
char s[sizeof(buffer)];
|
||||
|
||||
*p = ' ';
|
||||
n = sscanf(token, "%s %d", s, &nbits);
|
||||
if (n != 2)
|
||||
return -1;
|
||||
|
||||
err = IpAddr(s, &addr);
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
err = IpMask(nbits, &mask);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (state == STATE_READ_SRC)
|
||||
{
|
||||
src_addr = addr;
|
||||
src_mask = mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_addr = addr;
|
||||
dst_mask = mask;
|
||||
}
|
||||
}
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
token = strtok(NULL, " \t");
|
||||
}
|
||||
#undef STATE_READ_KEYWORD
|
||||
#undef STATE_READ_TYPE
|
||||
#undef STATE_READ_PORT
|
||||
#undef STATE_READ_SERVER
|
||||
#undef STATE_READ_RULE
|
||||
#undef STATE_READ_DELETE
|
||||
#undef STATE_READ_PROTO
|
||||
#undef STATE_READ_SRC
|
||||
#undef STATE_READ_DST
|
||||
|
||||
/* Convert port strings to numbers. This needs to be done after
|
||||
the string is parsed, because the prototype might not be designated
|
||||
before the ports (which might be symbolic entries in /etc/services) */
|
||||
|
||||
if (strlen(str_port) != 0)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = IpPort(str_port, proto, &proxy_port);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy_port = 0;
|
||||
}
|
||||
|
||||
if (strlen(str_server_port) != 0)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = IpPort(str_server_port, proto, &server_port);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
server_port = 0;
|
||||
}
|
||||
|
||||
/* Check that at least the server address has been defined */
|
||||
if (server_addr.s_addr == 0)
|
||||
return -1;
|
||||
|
||||
/* Add to linked list */
|
||||
proxy_entry = malloc(sizeof(struct proxy_entry));
|
||||
if (proxy_entry == NULL)
|
||||
return -1;
|
||||
|
||||
proxy_entry->proxy_type = proxy_type;
|
||||
proxy_entry->rule_index = rule_index;
|
||||
proxy_entry->proto = proto;
|
||||
proxy_entry->proxy_port = htons(proxy_port);
|
||||
proxy_entry->server_port = htons(server_port);
|
||||
proxy_entry->server_addr = server_addr;
|
||||
proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr;
|
||||
proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr;
|
||||
proxy_entry->src_mask = src_mask;
|
||||
proxy_entry->dst_mask = dst_mask;
|
||||
|
||||
RuleAdd(proxy_entry);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user