summaryrefslogtreecommitdiffstats
path: root/lib/libalias
diff options
context:
space:
mode:
authoreivind <eivind@FreeBSD.org>1998-01-09 21:13:35 +0000
committereivind <eivind@FreeBSD.org>1998-01-09 21:13:35 +0000
commit781f5bff105e2b341e76efe04ea322b2c9497ca8 (patch)
tree8444286dbbb89a371acf65fe1468b1a998a99e8c /lib/libalias
parent97367c5e32c06125a0fe56b5f85facbb1dd625ab (diff)
downloadFreeBSD-src-781f5bff105e2b341e76efe04ea322b2c9497ca8.zip
FreeBSD-src-781f5bff105e2b341e76efe04ea322b2c9497ca8.tar.gz
Teach libalias to work with IPFW firewalls (controlled by a flag).
Obtained from: Yes development tree (+ 10 lines of patches from Charles Mott, original libalias author)
Diffstat (limited to 'lib/libalias')
-rw-r--r--lib/libalias/HISTORY4
-rw-r--r--lib/libalias/Makefile2
-rw-r--r--lib/libalias/alias.c38
-rw-r--r--lib/libalias/alias.h17
-rw-r--r--lib/libalias/alias_db.c423
-rw-r--r--lib/libalias/alias_ftp.c7
-rw-r--r--lib/libalias/alias_irc.c3
-rw-r--r--lib/libalias/alias_local.h14
-rw-r--r--lib/libalias/libalias.360
9 files changed, 475 insertions, 93 deletions
diff --git a/lib/libalias/HISTORY b/lib/libalias/HISTORY
index 78a7e08..5d29e34 100644
--- a/lib/libalias/HISTORY
+++ b/lib/libalias/HISTORY
@@ -120,3 +120,7 @@ Version 2.4: September 1, 1997 (cjm)
This part of the code was incorrectly re-implemented
in version 2.1.
+Version 2.5: December, 1997 (ee)
+ - Added PKT_ALIAS_PUNCH_FW mode for firewall
+ bypass of FTP/IRC DCC data connections. Also added
+ improved TCP connection monitoring.
diff --git a/lib/libalias/Makefile b/lib/libalias/Makefile
index 3c291b2..6ce9e46 100644
--- a/lib/libalias/Makefile
+++ b/lib/libalias/Makefile
@@ -1,6 +1,6 @@
LIB= alias
SHLIB_MAJOR= 2
-SHLIB_MINOR= 4
+SHLIB_MINOR= 5
CFLAGS+=-Wall -I${.CURDIR}
SRCS= alias.c alias_db.c alias_ftp.c alias_irc.c alias_util.c alias_old.c
MAN3=libalias.3
diff --git a/lib/libalias/alias.c b/lib/libalias/alias.c
index a9c1e3b..c8ef65a 100644
--- a/lib/libalias/alias.c
+++ b/lib/libalias/alias.c
@@ -73,6 +73,8 @@
- Eliminated PacketAliasIn2() and
PacketAliasOut2() as poorly conceived.
+ See HISTORY file for additional revisions.
+
*/
#include <stdio.h>
@@ -149,12 +151,15 @@ TcpMonitorIn(struct ip *pip, struct alias_link *link)
switch (GetStateIn(link))
{
- case 0:
- if (tc->th_flags & TH_SYN) SetStateIn(link, 1);
+ case ALIAS_TCP_STATE_NOT_CONNECTED:
+ if (tc->th_flags & TH_SYN)
+ SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
break;
- case 1:
+ case ALIAS_TCP_STATE_CONNECTED:
if (tc->th_flags & TH_FIN
- || tc->th_flags & TH_RST) SetStateIn(link, 2);
+ || tc->th_flags & TH_RST)
+ SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
+ break;
}
}
@@ -167,12 +172,15 @@ TcpMonitorOut(struct ip *pip, struct alias_link *link)
switch (GetStateOut(link))
{
- case 0:
- if (tc->th_flags & TH_SYN) SetStateOut(link, 1);
+ case ALIAS_TCP_STATE_NOT_CONNECTED:
+ if (tc->th_flags & TH_SYN)
+ SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
break;
- case 1:
+ case ALIAS_TCP_STATE_CONNECTED:
if (tc->th_flags & TH_FIN
- || tc->th_flags & TH_RST) SetStateOut(link, 2);
+ || tc->th_flags & TH_RST)
+ SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
+ break;
}
}
@@ -776,7 +784,7 @@ TcpAliasOut(struct ip *pip, int maxpacketsize)
|| 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 */
@@ -977,6 +985,11 @@ PacketAliasIn(char *ptr, int maxpacketsize)
pip = (struct ip *) ptr;
alias_addr = pip->ip_dst;
+ /* Defense against mangled packets */
+ if (ntohs(pip->ip_len) > maxpacketsize
+ || (pip->ip_hl<<2) > maxpacketsize)
+ return PKT_ALIAS_IGNORED;
+
iresult = PKT_ALIAS_IGNORED;
if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
{
@@ -1002,7 +1015,7 @@ PacketAliasIn(char *ptr, int maxpacketsize)
{
iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
SetFragmentAddr(link, pip->ip_dst);
- }
+ }
else
{
iresult = PKT_ALIAS_ERROR;
@@ -1049,6 +1062,11 @@ PacketAliasOut(char *ptr, /* valid IP packet */
ClearCheckNewLink();
pip = (struct ip *) ptr;
+ /* Defense against mangled packets */
+ if (ntohs(pip->ip_len) > maxpacketsize
+ || (pip->ip_hl<<2) > maxpacketsize)
+ return PKT_ALIAS_IGNORED;
+
addr_save = GetDefaultAliasAddress();
if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
{
diff --git a/lib/libalias/alias.h b/lib/libalias/alias.h
index 50d8056..9d1f755 100644
--- a/lib/libalias/alias.h
+++ b/lib/libalias/alias.h
@@ -26,11 +26,17 @@ struct alias_link;
PacketAliasInit(void);
extern void
+ PacketAliasUninit(void);
+
+ extern void
PacketAliasSetAddress(struct in_addr);
extern unsigned int
PacketAliasSetMode(unsigned int, unsigned int);
+ extern void
+ PacketAliasSetFWBase(unsigned int, unsigned int);
+
/* Packet Handling */
extern int
PacketAliasIn(char *, int maxpacketsize);
@@ -136,6 +142,14 @@ extern u_short InternetChecksum(u_short *, int);
bit is set after a call to PacketAliasInit(). */
#define PKT_ALIAS_RESET_ON_ADDR_CHANGE 0x20
+/* If PKT_ALIAS_PUNCH_FW is set, active FTP and IRC DCC connections
+ will create a 'hole' in the firewall to allow the transfers to
+ work. Where (IPFW "line-numbers") the hole is created is
+ controlled by PacketAliasSetFWBase(base, size). The hole will be
+ attached to that particular alias_link, so when the link goes away
+ so do the hole. */
+#define PKT_ALIAS_PUNCH_FW 0x40
+
/* Return Codes */
#define PKT_ALIAS_ERROR -1
#define PKT_ALIAS_OK 1
@@ -143,8 +157,5 @@ extern u_short InternetChecksum(u_short *, int);
#define PKT_ALIAS_UNRESOLVED_FRAGMENT 3
#define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4
-#undef __libalias_version
-#define __libalias_version "2.4"
-
#endif
/*lint -restore */
diff --git a/lib/libalias/alias_db.c b/lib/libalias/alias_db.c
index 3579dca..d5dff37 100644
--- a/lib/libalias/alias_db.c
+++ b/lib/libalias/alias_db.c
@@ -90,7 +90,7 @@
SetExpire() function added. (cjm)
DeleteLink() no longer frees memory association with a pointer
- to a fragment (this bug was first recognized by E. Eiklund in
+ to a fragment (this bug was first recognized by E. Eklund in
v1.9).
Version 2.1: May, 1997 (cjm)
@@ -102,6 +102,8 @@
added to the API. The first function is a more generalized
version of PacketAliasPermanentLink(). The second function
implements static network address translation.
+
+ See HISTORY file for additional revisions.
*/
@@ -114,6 +116,7 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <osreldate.h>
/* BSD network include files */
#include <netinet/in_systm.h>
@@ -143,10 +146,33 @@
/* Timouts (in seconds) for different link types) */
#define ICMP_EXPIRE_TIME 60
#define UDP_EXPIRE_TIME 60
-#define TCP_EXPIRE_TIME 90
#define FRAGMENT_ID_EXPIRE_TIME 10
#define FRAGMENT_PTR_EXPIRE_TIME 30
+/* TCP link expire time for different cases */
+/* When the link has been used and closed - minimal grace time to
+ allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
+#ifndef TCP_EXPIRE_DEAD
+# define TCP_EXPIRE_DEAD 10
+#endif
+
+/* When the link has been used and closed on one side - the other side
+ is allowed to still send data */
+#ifndef TCP_EXPIRE_SINGLEDEAD
+# define TCP_EXPIRE_SINGLEDEAD 90
+#endif
+
+/* When the link isn't yet up */
+#ifndef TCP_EXPIRE_INITIAL
+# define TCP_EXPIRE_INITIAL 300
+#endif
+
+/* When the link is up */
+#ifndef TCP_EXPIRE_CONNECTED
+# define TCP_EXPIRE_CONNECTED 86400
+#endif
+
+
/* Dummy port number codes used for FindLinkIn/Out() and AddLink().
These constants can be anything except zero, which indicates an
unknown port numbea. */
@@ -206,6 +232,7 @@ struct tcp_dat
{
struct tcp_state state;
struct ack_data_record ack[N_LINK_TCP_DATA];
+ int fwhole; /* Which firewall record is used for this hole? */
};
struct alias_link /* Main data structure */
@@ -234,6 +261,7 @@ struct alias_link /* Main data structure */
#define LINK_UNKNOWN_DEST_ADDR 0x02
#define LINK_PERMANENT 0x04
#define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
+#define LINK_UNFIREWALLED 0x08
int timestamp; /* Time link was last accessed */
int expire_time; /* Expire time for link */
@@ -309,12 +337,16 @@ static int deleteAllLinks; /* If equal to zero, DeleteLink() */
static FILE *monitorFile; /* File descriptor for link */
/* statistics monitoring file */
-static int firstCall = 1; /* Needed by InitAlias() */
-
static int newDefaultLink; /* Indicates if a new aliasing */
/* link has been created after a */
/* call to PacketAliasIn/Out(). */
+static int fireWallFD = -1; /* File descriptor to be able to */
+ /* control firewall. Opened by */
+ /* PacketAliasSetMode on first */
+ /* setting the PKT_ALIAS_PUNCH_FW */
+ /* flag. */
+
@@ -344,6 +376,14 @@ static int SeqDiff(u_long, u_long);
static void ShowAliasStats(void);
+/* Firewall control */
+static void InitPunchFW(void);
+static void UninitPunchFW(void);
+static void ClearFWHole(struct alias_link *link);
+
+/* Log file control */
+static void InitPacketAliasLog(void);
+static void UninitPacketAliasLog(void);
static u_int
StartPointIn(struct in_addr alias_addr,
@@ -429,6 +469,7 @@ Link creation and deletion:
IncrementalCleanup() - look for stale links in a single chain
DeleteLink() - remove link
AddLink() - add link
+ ReLink() - change link
Link search:
FindLinkOut() - find link for outgoing packets
@@ -451,6 +492,11 @@ AddLink(struct in_addr, struct in_addr, struct in_addr,
u_short, u_short, int, int);
static struct alias_link *
+ReLink(struct alias_link *,
+ struct in_addr, struct in_addr, struct in_addr,
+ u_short, u_short, int, int);
+
+static struct alias_link *
FindLinkOut(struct in_addr, struct in_addr, u_short, u_short, int);
static struct alias_link *
@@ -680,8 +726,8 @@ IncrementalCleanup(void)
struct tcp_dat *tcp_aux;
tcp_aux = link->data.tcp;
- if (tcp_aux->state.in != 1
- || tcp_aux->state.out != 1)
+ if (tcp_aux->state.in != ALIAS_TCP_STATE_CONNECTED
+ || tcp_aux->state.out != ALIAS_TCP_STATE_CONNECTED)
{
DeleteLink(link);
icount++;
@@ -706,6 +752,9 @@ DeleteLink(struct alias_link *link)
if (deleteAllLinks == 0 && link->flags & LINK_PERMANENT)
return;
+/* Delete associatied firewall hole, if any */
+ ClearFWHole(link);
+
/* Adjust output table pointers */
link_last = link->last_out;
link_next = link->next_out;
@@ -820,7 +869,7 @@ AddLink(struct in_addr src_addr,
link->expire_time = UDP_EXPIRE_TIME;
break;
case LINK_TCP:
- link->expire_time = TCP_EXPIRE_TIME;
+ link->expire_time = TCP_EXPIRE_INITIAL;
break;
case LINK_FRAGMENT_ID:
link->expire_time = FRAGMENT_ID_EXPIRE_TIME;
@@ -889,12 +938,13 @@ AddLink(struct in_addr src_addr,
int i;
tcpLinkCount++;
- aux_tcp->state.in = 0;
- aux_tcp->state.out = 0;
+ aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
+ aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
aux_tcp->state.index = 0;
aux_tcp->state.ack_modified = 0;
for (i=0; i<N_LINK_TCP_DATA; i++)
aux_tcp->ack[i].active = 0;
+ aux_tcp->fwhole = -1;
}
else
{
@@ -924,6 +974,30 @@ AddLink(struct in_addr src_addr,
return(link);
}
+static struct alias_link *
+ReLink(struct alias_link *old_link,
+ struct in_addr src_addr,
+ struct in_addr dst_addr,
+ struct in_addr alias_addr,
+ u_short src_port,
+ u_short dst_port,
+ int alias_port_param, /* if less than zero, alias */
+ int link_type) /* port will be automatically */
+{ /* chosen. If greater than */
+ struct alias_link *new_link; /* zero, equal to alias port */
+
+ new_link = AddLink(src_addr, dst_addr, alias_addr,
+ src_port, dst_port, alias_port_param,
+ link_type);
+ if (new_link != NULL &&
+ old_link->link_type == LINK_TCP &&
+ old_link->data.tcp &&
+ old_link->data.tcp->fwhole > 0) {
+ PunchFWHole(new_link);
+ }
+ DeleteLink(old_link);
+ return new_link;
+}
static struct alias_link *
FindLinkOut(struct in_addr src_addr,
@@ -1057,55 +1131,34 @@ FindLinkIn(struct in_addr dst_addr,
if (link_fully_specified != NULL)
{
- return (link_fully_specified);
+ return link_fully_specified;
}
else if (link_unknown_dst_port != NULL)
{
- if (replace_partial_links)
- {
- link = AddLink(link_unknown_dst_port->src_addr, dst_addr,
- alias_addr,
- link_unknown_dst_port->src_port, dst_port,
- alias_port, link_type);
- DeleteLink(link_unknown_dst_port);
- return(link);
- }
- else
- {
- return(link_unknown_dst_port);
- }
+ return replace_partial_links
+ ? ReLink(link_unknown_dst_port,
+ link_unknown_dst_port->src_addr, dst_addr, alias_addr,
+ link_unknown_dst_port->src_port, dst_port, alias_port,
+ link_type)
+ : link_unknown_dst_port;
}
else if (link_unknown_dst_addr != NULL)
{
- if (replace_partial_links)
- {
- link = AddLink(link_unknown_dst_addr->src_addr, dst_addr,
- alias_addr,
- link_unknown_dst_addr->src_port, dst_port,
- alias_port, link_type);
- DeleteLink(link_unknown_dst_addr);
- return(link);
- }
- else
- {
- return(link_unknown_dst_addr);
- }
+ return replace_partial_links
+ ? ReLink(link_unknown_dst_addr,
+ link_unknown_dst_addr->src_addr, dst_addr, alias_addr,
+ link_unknown_dst_addr->src_port, dst_port, alias_port,
+ link_type)
+ : link_unknown_dst_addr;
}
else if (link_unknown_all != NULL)
{
- if (replace_partial_links)
- {
- link = AddLink(link_unknown_all->src_addr, dst_addr,
- alias_addr,
- link_unknown_all->src_port, dst_port,
- alias_port, link_type);
- DeleteLink(link_unknown_all);
- return(link);
- }
- else
- {
- return(link_unknown_all);
- }
+ return replace_partial_links
+ ? ReLink(link_unknown_all,
+ link_unknown_all->src_addr, dst_addr, alias_addr,
+ link_unknown_all->src_port, dst_port, alias_port,
+ link_type)
+ : link_unknown_all;
}
else
{
@@ -1389,7 +1442,24 @@ void
SetStateIn(struct alias_link *link, int state)
{
/* TCP input state */
- (link->data.tcp)->state.in = state;
+ switch (state) {
+ case ALIAS_TCP_STATE_DISCONNECTED:
+ if (link->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED) {
+ link->expire_time = TCP_EXPIRE_DEAD;
+ } else {
+ link->expire_time = TCP_EXPIRE_SINGLEDEAD;
+ }
+ link->data.tcp->state.in = state;
+ break;
+ case ALIAS_TCP_STATE_CONNECTED:
+ link->expire_time = TCP_EXPIRE_CONNECTED;
+ /*FALLTHROUGH*/
+ case ALIAS_TCP_STATE_NOT_CONNECTED:
+ link->data.tcp->state.in = state;
+ break;
+ default:
+ abort();
+ }
}
@@ -1397,7 +1467,24 @@ void
SetStateOut(struct alias_link *link, int state)
{
/* TCP output state */
- (link->data.tcp)->state.out = state;
+ switch (state) {
+ case ALIAS_TCP_STATE_DISCONNECTED:
+ if (link->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED) {
+ link->expire_time = TCP_EXPIRE_DEAD;
+ } else {
+ link->expire_time = TCP_EXPIRE_SINGLEDEAD;
+ }
+ link->data.tcp->state.out = state;
+ break;
+ case ALIAS_TCP_STATE_CONNECTED:
+ link->expire_time = TCP_EXPIRE_CONNECTED;
+ /*FALLTHROUGH*/
+ case ALIAS_TCP_STATE_NOT_CONNECTED:
+ link->data.tcp->state.out = state;
+ break;
+ default:
+ abort();
+ }
}
@@ -1405,7 +1492,7 @@ int
GetStateIn(struct alias_link *link)
{
/* TCP input state */
- return( (link->data.tcp)->state.in);
+ return link->data.tcp->state.in;
}
@@ -1413,7 +1500,7 @@ int
GetStateOut(struct alias_link *link)
{
/* TCP output state */
- return( (link->data.tcp)->state.out);
+ return link->data.tcp->state.out;
}
@@ -1471,12 +1558,17 @@ GetAliasPort(struct alias_link *link)
return(link->alias_port);
}
+u_short
+GetDestPort(struct alias_link *link)
+{
+ return(link->dst_port);
+}
void
SetAckModified(struct alias_link *link)
{
/* Indicate that ack numbers have been modified in a TCP connection */
- (link->data.tcp)->state.ack_modified = 1;
+ link->data.tcp->state.ack_modified = 1;
}
@@ -1484,7 +1576,7 @@ int
GetAckModified(struct alias_link *link)
{
/* See if ack numbers have been modified */
- return( (link->data.tcp)->state.ack_modified );
+ return link->data.tcp->state.ack_modified;
}
@@ -1511,7 +1603,7 @@ packet size was altered is searched.
{
struct ack_data_record x;
- x = (link->data.tcp)->ack[i];
+ x = link->data.tcp->ack[i];
if (x.active == 1)
{
int ack_diff;
@@ -1562,7 +1654,7 @@ packet size was altered is searched.
{
struct ack_data_record x;
- x = (link->data.tcp)->ack[i];
+ x = link->data.tcp->ack[i];
if (x.active == 1)
{
int seq_diff;
@@ -1615,14 +1707,14 @@ been altered, then this list will begin to overwrite itself.
x.delta = delta;
x.active = 1;
- i = (link->data.tcp)->state.index;
- (link->data.tcp)->ack[i] = x;
+ i = link->data.tcp->state.index;
+ link->data.tcp->ack[i] = x;
i++;
if (i == N_LINK_TCP_DATA)
- (link->data.tcp)->state.index = 0;
+ link->data.tcp->state.index = 0;
else
- (link->data.tcp)->state.index = i;
+ link->data.tcp->state.index = i;
}
void
@@ -1722,7 +1814,7 @@ HouseKeeping(void)
/* Init the log file and enable logging */
-void
+static void
InitPacketAliasLog(void)
{
if ((~packetAliasMode & PKT_ALIAS_LOG)
@@ -1736,7 +1828,7 @@ InitPacketAliasLog(void)
/* Close the log-file and disable logging. */
-void
+static void
UninitPacketAliasLog(void)
{
if( monitorFile )
@@ -1758,6 +1850,7 @@ UninitPacketAliasLog(void)
PacketAliasRedirectDelete()
PacketAliasSetAddress()
PacketAliasInit()
+ PacketAliasUninit()
PacketAliasSetMode()
(prototypes in alias.h)
@@ -1868,6 +1961,7 @@ PacketAliasInit(void)
int i;
struct timeval tv;
struct timezone tz;
+ static int firstCall = 1;
if (firstCall == 1)
{
@@ -1881,6 +1975,7 @@ PacketAliasInit(void)
for (i=0; i<LINK_TABLE_IN_SIZE; i++)
linkTableIn[i] = NULL;
+ atexit(PacketAliasUninit);
firstCall = 0;
}
else
@@ -1907,11 +2002,19 @@ PacketAliasInit(void)
| PKT_ALIAS_RESET_ON_ADDR_CHANGE;
}
+void
+PacketAliasUninit(void) {
+ deleteAllLinks = 1;
+ CleanupAliasData();
+ deleteAllLinks = 0;
+ UninitPacketAliasLog();
+ UninitPunchFW();
+}
+
/* Change mode for some operations */
unsigned int
-PacketAliasSetMode
-(
+PacketAliasSetMode(
unsigned int flags, /* Which state to bring flags to */
unsigned int mask /* Mask of which flags to affect (use 0 to do a
probe for flag values) */
@@ -1921,12 +2024,21 @@ PacketAliasSetMode
if (flags & mask & PKT_ALIAS_LOG)
{
InitPacketAliasLog(); /* Do the enable */
- }
+ } else
/* _Disable_ logging? */
if (~flags & mask & PKT_ALIAS_LOG) {
UninitPacketAliasLog();
}
+/* Start punching holes in the firewall? */
+ if (flags & mask & PKT_ALIAS_PUNCH_FW) {
+ InitPunchFW();
+ } else
+/* Stop punching holes in the firewall? */
+ if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
+ UninitPunchFW();
+ }
+
/* Other flags can be set/cleared without special action */
packetAliasMode = (flags & mask) | (packetAliasMode & ~mask);
return packetAliasMode;
@@ -1938,3 +2050,182 @@ PacketAliasCheckNewLink(void)
{
return newDefaultLink;
}
+
+
+/*****************
+ Code to support firewall punching. This shouldn't really be in this
+ file, but making variables global is evil too.
+ ****************/
+
+/* Firewall include files */
+#include <sys/queue.h>
+#include <netinet/ip_fw.h>
+#include <string.h>
+#include <err.h>
+
+static void ClearAllFWHoles(void);
+
+static int fireWallBaseNum; /* The first firewall entry free for our use */
+static int fireWallNumNums; /* How many entries can we use? */
+static int fireWallActiveNum; /* Which entry did we last use? */
+static char *fireWallField; /* bool array for entries */
+
+#define fw_setfield(field, num) \
+do { \
+ (field)[num] = 1; \
+} /*lint -save -e717 */ while(0) /*lint -restore */
+#define fw_clrfield(field, num) \
+do { \
+ (field)[num] = 0; \
+} /*lint -save -e717 */ while(0) /*lint -restore */
+#define fw_tstfield(field, num) ((field)[num])
+
+void
+PacketAliasSetFWBase(unsigned int base, unsigned int num) {
+ fireWallBaseNum = base;
+ fireWallNumNums = num;
+}
+
+static void
+InitPunchFW(void) {
+ fireWallField = malloc(fireWallNumNums);
+ if (fireWallField) {
+ memset(fireWallField, 0, fireWallNumNums);
+ if (fireWallFD < 0) {
+ fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ }
+ ClearAllFWHoles();
+ fireWallActiveNum = fireWallBaseNum;
+ }
+}
+
+static void
+UninitPunchFW(void) {
+ ClearAllFWHoles();
+ if (fireWallFD >= 0)
+ close(fireWallFD);
+ fireWallFD = -1;
+ if (fireWallField)
+ free(fireWallField);
+ fireWallField = NULL;
+ packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
+}
+
+/* Make a certain link go through the firewall */
+void
+PunchFWHole(struct alias_link *link) {
+ int r; /* Result code */
+ struct ip_fw rule; /* On-the-fly built rule */
+ int fwhole; /* Where to punch hole */
+
+/* Don't do anything unless we are asked to */
+ if ( !(packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
+ fireWallFD < 0 ||
+ link->link_type != LINK_TCP ||
+ !link->data.tcp)
+ return;
+
+ memset(&rule, 0, sizeof rule);
+
+/** Build rule **/
+
+ /* Find empty slot */
+ for (fwhole = fireWallActiveNum;
+ fwhole < fireWallBaseNum + fireWallNumNums &&
+ fw_tstfield(fireWallField, fwhole);
+ fwhole++)
+ ;
+ if (fwhole >= fireWallBaseNum + fireWallNumNums ||
+ fw_tstfield(fireWallField, fwhole)) {
+ for (fwhole = fireWallBaseNum;
+ fwhole < fireWallActiveNum &&
+ fw_tstfield(fireWallField, fwhole);
+ fwhole++)
+ ;
+ if (fwhole == fireWallActiveNum) {
+ /* No rule point empty - we can't punch more holes. */
+ fireWallActiveNum = fireWallBaseNum;
+ fprintf(stderr, "libalias: Unable to create firewall hole!\n");
+ return;
+ }
+ }
+ /* Start next search at next position */
+ fireWallActiveNum = fwhole+1;
+
+ /* Build generic part of the two rules */
+ rule.fw_number = fwhole;
+#if __FreeBSD_version < 300000
+ rule.fw_nsp = 1; /* 1 source port */
+ rule.fw_ndp = 1; /* 1 destination port */
+#else
+ rule.fw_nports = 1; /* Number of source ports; dest ports follow */
+#endif
+ rule.fw_flg = IP_FW_F_ACCEPT;
+ rule.fw_prot = IPPROTO_TCP;
+ rule.fw_smsk.s_addr = INADDR_BROADCAST;
+ rule.fw_dmsk.s_addr = INADDR_BROADCAST;
+
+ /* Build and apply specific part of the rules */
+ rule.fw_src = GetOriginalAddress(link);
+ rule.fw_dst = GetDestAddress(link);
+ rule.fw_pts[0] = ntohs(GetOriginalPort(link));
+ rule.fw_pts[1] = ntohs(GetDestPort(link));
+
+ /* Skip non-bound links - XXX should not be strictly necessary,
+ but seems to leave hole if not done. Leak of non-bound links?
+ (Code should be left even if the problem is fixed - it is a
+ clear optimization) */
+ if (rule.fw_pts[0] != 0 && rule.fw_pts[1] != 0) {
+ r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule);
+ if (r)
+ err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
+ rule.fw_src = GetDestAddress(link);
+ rule.fw_dst = GetOriginalAddress(link);
+ rule.fw_pts[0] = ntohs(GetDestPort(link));
+ rule.fw_pts[1] = ntohs(GetOriginalPort(link));
+ r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule);
+ if (r)
+ err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
+ }
+/* Indicate hole applied */
+ link->data.tcp->fwhole = fwhole;
+ fw_setfield(fireWallField, fwhole);
+}
+
+/* Remove a hole in a firewall associated with a particular alias
+ link. Calling this too often is harmless. */
+static void
+ClearFWHole(struct alias_link *link) {
+ if (link->link_type == LINK_TCP && link->data.tcp) {
+ int fwhole = link->data.tcp->fwhole; /* Where is the firewall hole? */
+ struct ip_fw rule;
+
+ if (fwhole < 0)
+ return;
+
+ memset(&rule, 0, sizeof rule);
+ rule.fw_number = fwhole;
+ while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule))
+ ;
+ fw_clrfield(fireWallField, fwhole);
+ link->data.tcp->fwhole = -1;
+ }
+}
+
+/* Clear out the entire range dedicated to firewall holes. */
+static void
+ClearAllFWHoles(void) {
+ struct ip_fw rule; /* On-the-fly built rule */
+ int i;
+
+ if (fireWallFD < 0)
+ return;
+
+ memset(&rule, 0, sizeof rule);
+ for (i = fireWallBaseNum; i < fireWallBaseNum + fireWallNumNums; i++) {
+ rule.fw_number = i;
+ while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule))
+ ;
+ }
+ memset(fireWallField, 0, fireWallNumNums);
+}
diff --git a/lib/libalias/alias_ftp.c b/lib/libalias/alias_ftp.c
index e03c04b..df6d02c 100644
--- a/lib/libalias/alias_ftp.c
+++ b/lib/libalias/alias_ftp.c
@@ -32,6 +32,8 @@
Very minor changes to conform with
local/global/function naming conventions
withing the packet alising module.
+
+ See HISTORY file for record of revisions.
*/
/* Includes */
@@ -150,6 +152,9 @@ NewFtpPortCommand(struct ip *pip,
int slen, hlen, tlen, dlen;
struct tcphdr *tc;
+/* Punch hole in firewall */
+ PunchFWHole(ftp_link);
+
/* Calculate data length of TCP packet */
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
hlen = (pip->ip_hl + tc->th_off) << 2;
@@ -167,7 +172,7 @@ NewFtpPortCommand(struct ip *pip,
/* Decompose alias address into quad format */
alias_address = GetAliasAddress(link);
- ptr = (char *) &alias_address;
+ ptr = (u_char *) &alias_address.s_addr;
a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
/* Decompose alias port into pair format */
diff --git a/lib/libalias/alias_irc.c b/lib/libalias/alias_irc.c
index 3657368..933e3c6 100644
--- a/lib/libalias/alias_irc.c
+++ b/lib/libalias/alias_irc.c
@@ -223,6 +223,9 @@ lFOUND_CTCP:
struct in_addr alias_address; /* Address from aliasing */
u_short alias_port; /* Port given by aliasing */
+ /* Generate firewall hole as appropriate */
+ PunchFWHole(dcc_link);
+
alias_address = GetAliasAddress(link);
iCopy += snprintf(&newpacket[iCopy],
sizeof(newpacket)-iCopy,
diff --git a/lib/libalias/alias_local.h b/lib/libalias/alias_local.h
index d71c80a..ba5f31f 100644
--- a/lib/libalias/alias_local.h
+++ b/lib/libalias/alias_local.h
@@ -12,6 +12,8 @@
<updated several times by original author and Eivind Eiklund>
*/
+#ifndef ALIAS_LOCAL_H
+#define ALIAS_LOCAL_H
extern int packetAliasMode;
@@ -53,7 +55,6 @@ FindOriginalAddress(struct in_addr);
struct in_addr
FindAliasAddress(struct in_addr);
-
/* External data access/modification */
void GetFragmentAddr(struct alias_link *, struct in_addr *);
void SetFragmentAddr(struct alias_link *, struct in_addr);
@@ -77,6 +78,8 @@ int GetDeltaSeqOut(struct ip *, struct alias_link *);
void AddSeq(struct ip *, struct alias_link *, int);
void SetExpire(struct alias_link *, int);
void ClearCheckNewLink(void);
+void PunchFWHole(struct alias_link *);
+
/* Housekeeping function */
void HouseKeeping(void);
@@ -86,8 +89,11 @@ void HouseKeeping(void);
void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
void AliasHandleIrcOut(struct ip *pip, struct alias_link *link, int maxsize );
-/* Log file control */
-void InitPacketAliasLog(void);
-void UninitPacketAliasLog(void);
+enum alias_tcp_state {
+ ALIAS_TCP_STATE_NOT_CONNECTED,
+ ALIAS_TCP_STATE_CONNECTED,
+ ALIAS_TCP_STATE_DISCONNECTED
+};
/*lint -restore */
+#endif /* defined(ALIAS_LOCAL_H) */
diff --git a/lib/libalias/libalias.3 b/lib/libalias/libalias.3
index 6c86232..51f3194 100644
--- a/lib/libalias/libalias.3
+++ b/lib/libalias/libalias.3
@@ -20,8 +20,10 @@ of the text.
1. Introduction
2. Initialization and Control
2.1 PacketAliasInit()
- 2.2 PacketAliasSetAddress()
- 2.3 PacketAliasSetMode()
+ 2.2 PacketAliasUninit()
+ 2.3 PacketAliasSetAddress()
+ 2.4 PacketAliasSetMode()
+ 2.5 PacketAliasSetFWBase()
3. Packet Handling
3.1 PacketAliasOut()
3.2 PacketAliasIn()
@@ -116,7 +118,24 @@ PacketAliasSetMode().
It is mandatory that this function be called
at the beginning of a program prior to any
packet handling.
-.Ss 2.2 PacketAliasSetAddress()
+.Ss 2.2 PacketAliasUnInit()
+
+.Ft void
+.Fn PacketAliasUnInit "void"
+
+This function has no argument or return
+value and is used to clear any resources
+attached to internal data structures.
+
+This functions should be called when a
+program stop using the aliasing engine;
+it do, among other things, clear out any
+firewall holes. To provide backwards
+compatibility and extra security, it is
+added to the atexit() chain by
+PacketAliasInit(). Calling it multiple
+times is harmless.
+.Ss 2.3 PacketAliasSetAddress()
.Ft void
.Fn PacketAliasSetAddress "struct in_addr addr"
@@ -145,7 +164,7 @@ call).
It is mandatory that this function be called
prior to any packet handling.
-.Ss 2.3 PacketAliasSetMode()
+.Ss 2.4 PacketAliasSetMode()
.Ft void
.Fn PacketAliasSetMode "int mode" "int mask"
@@ -224,7 +243,31 @@ change or remain the same between dial-ups.
If this mode bit is not set, it the link table
will never be reset in the event of an
address change.
+.It PKT_ALIAS_PUNCH_FW.
+This option make libalias `punch holes' in an
+ipfw based firewall for FTP/IRC DCC connections.
+The holes punched are bound by from/to IP address
+and port; it will not be possible to use a hole
+for another connection. A hole is removed when
+the connection that use it die. To cater for
+unexpected death of a program using libalias (e.g
+kill -9), changing the state of the flag will
+clear the entire ipfw range allocated for holes.
+This will also happen on the initial call to
+PacketAliasSetFWBase(). This call must happen
+prior to setting this flag.
+
.El
+
+.Ss 2.5 PacketAliasSetFWBase()
+
+.Ft void
+.Fn PacketAliasSetFWBase "unsigned int base" "unsigned int num"
+
+Set IPFW range allocated for punching firewall holes (with the
+PKT_ALIAS_PUNCH_FW flag). The range will be cleared for all rules on
+initialization.
+
.Sh 3. Packet Handling
The packet handling functions are used to
modify incoming (remote->local) and outgoing
@@ -295,7 +338,7 @@ protocols place addresss and port information in
the encapsulated data stream which have to be
modified and can account for changes in packet
length. Well known examples of such protocols
-are FTP and IRC.
+are FTP and IRC DCC.
Return codes:
.Bl -hang -offset left
@@ -570,9 +613,10 @@ valid, PacketAliasInternetChecksum() will return zero.
.Sh 7. Authors
Charles Mott (cmott@srv.net), versions 1.0 - 1.8, 2.0 - 2.4.
-Eivind Eiklund (eivind@freebsd.org), versions 1.8b and 1.9.
-Added IRC support as well as contributing a number of
-architectural improvements.
+Eivind Eklund (eivind@freebsd.org), versions 1.8b, 1.9 and
+2.5. Added IRC DCC support as well as contributing a number of
+architectural improvements; added the firewall bypass
+for FTP/IRC DCC.
.Sh 8. Acknowledgments
OpenPOWER on IntegriCloud