-/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
+/*
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 2001 Charles Mott <cmott@scientech.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Based upon:
+ * $FreeBSD: src/lib/libalias/alias.c,v 1.16.2.7 2001/08/21 03:50:25 brian Exp $
+ */
+
/*
Alias.c provides supervisory control for the functions of the
packet aliasing software. It consists of routines to monitor
function calls, so other segments of the program need not know
about the underlying data structures. Alias_ftp.c contains
special code for modifying the ftp PORT command used to establish
- data connections, while alias_irc.c do the same for IRC
+ data connections, while alias_irc.c does the same for IRC
DCC. Alias_util.c contains a few utility routines.
- This software is placed into the public domain with no restrictions
- on its distribution.
-
Version 1.0 August, 1996 (cjm)
Version 1.1 August 20, 1996 (cjm)
Version 2.3 Dec 1998 (dillon)
- Major bounds checking additions, see FreeBSD/CVS
- See HISTORY file for additional revisions.
+ Version 3.1 May, 2000 (salander)
+ - Added hooks to handle PPTP.
-*/
+ Version 3.2 July, 2000 (salander and satoh)
+ - Added PacketUnaliasOut routine.
+ - Added hooks to handle RTSP/RTP.
-#include <stdio.h>
-#include <unistd.h>
+ See HISTORY file for additional revisions.
+*/
-#include <sys/param.h>
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
-#ifndef IPPROTO_GRE
-#define IPPROTO_GRE 47
-#endif
+#include <stdio.h>
#include "alias_local.h"
#include "alias.h"
#define IRC_CONTROL_PORT_NUMBER_1 6667
#define IRC_CONTROL_PORT_NUMBER_2 6668
#define CUSEEME_PORT_NUMBER 7648
+#define RTSP_CONTROL_PORT_NUMBER_1 554
+#define RTSP_CONTROL_PORT_NUMBER_2 7070
+#define PPTP_CONTROL_PORT_NUMBER 1723
TcpMonitorIn() -- These routines monitor TCP connections, and
TcpMonitorOut() delete a link when a connection is closed.
-These routines look for SYN, ACK and RST flags to determine when TCP
+ DoMSSClamp() -- Clamps the MSS of the given TCP header to the
+ value in packetAliasMSS.
+
+These routines look for SYN, FIN and RST flags to determine when TCP
connections open and close. When a TCP connection closes, the data
structure containing packet aliasing information is deleted after
a timeout period.
static void TcpMonitorOut(struct ip *, struct alias_link *);
+static u_short packetAliasMSS;
+
+void PacketAliasClampMSS(u_short mss)
+{
+ packetAliasMSS = mss;
+}
+
+static void DoMSSClamp(struct tcphdr *tc)
+{
+ u_char *option = (u_char *) tc + sizeof(*tc);
+ u_char *optionEnd = option + ((tc->th_off << 2) - sizeof(*tc));
+
+#define TEST_5618045 0
+#if TEST_5618045
+ if ((ntohs(tc->th_dport) == 8080 || ntohs(tc->th_sport) == 8080) && tc->th_off > 5) {
+ option[0] = 0xF4;
+ option[1] = 0;
+ }
+#endif
+
+ while (optionEnd > option)
+ {
+ /* Bounds checking to avoid infinite loops */
+ if (option[0] == TCPOPT_EOL)
+ break;
+
+ if (option[0] == TCPOPT_NOP) {
+ ++option;
+ continue;
+ } else {
+ if (optionEnd - option < 2)
+ break;
+ if (option[1] < 2 || option + option[1] >= optionEnd)
+ break;
+ }
+
+ switch (option[0])
+ {
+ case TCPOPT_MAXSEG:
+ if (option[1] == 4)
+ {
+ u_short *mssPtr = (u_short *) option + 1;
+ u_short mssVal = ntohs(*mssPtr);
+
+ if (packetAliasMSS < mssVal)
+ {
+ int accumulate = mssVal;
+ int accnetorder = 0 ;
+
+ accumulate -= packetAliasMSS;
+ *mssPtr = htons(packetAliasMSS);
+ accnetorder = htons(accumulate);
+ ADJUST_CHECKSUM(accnetorder, tc->th_sum);
+ }
+
+ option = optionEnd;
+ }
+ break;
+
+ default:
+ option += option[1];
+ break;
+ }
+ }
+}
+
static void
TcpMonitorIn(struct ip *pip, struct alias_link *link)
{
switch (GetStateIn(link))
{
case ALIAS_TCP_STATE_NOT_CONNECTED:
- if (tc->th_flags & TH_SYN)
+ if (tc->th_flags & TH_RST)
+ SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
+ else if (tc->th_flags & TH_SYN)
+ {
SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
+
+ if (packetAliasMSS)
+ DoMSSClamp(tc);
+ }
break;
case ALIAS_TCP_STATE_CONNECTED:
- if (tc->th_flags & TH_FIN
- || tc->th_flags & TH_RST)
+ if (tc->th_flags & (TH_FIN | TH_RST))
SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
break;
}
switch (GetStateOut(link))
{
case ALIAS_TCP_STATE_NOT_CONNECTED:
- if (tc->th_flags & TH_SYN)
+ if (tc->th_flags & TH_RST)
+ SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
+ else if (tc->th_flags & TH_SYN)
+ {
SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
+
+ if (packetAliasMSS)
+ DoMSSClamp(tc);
+ }
break;
case ALIAS_TCP_STATE_CONNECTED:
- if (tc->th_flags & TH_FIN
- || tc->th_flags & TH_RST)
+ if (tc->th_flags & (TH_FIN | TH_RST))
SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
break;
}
/* Protocol Specific Packet Aliasing Routines
- IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2(), IcmpAliasIn3()
- IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2(), IcmpAliasOut3()
+ IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
+ IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
+ ProtoAliasIn(), ProtoAliasOut()
UdpAliasIn(), UdpAliasOut()
TcpAliasIn(), TcpAliasOut()
any incoming packets. For TCP and UDP, ports are also re-mapped.
For ICMP echo/timestamp requests and replies, the following scheme
-is used: the id number is replaced by an alias for the outgoing
+is used: the ID number is replaced by an alias for the outgoing
packet.
ICMP error messages are handled by looking at the IP fragment
For TCP and UDP protocols, a port number is chosen for an outgoing
packet, and then incoming packets are identified by IP address and
port numbers. For TCP packets, there is additional logic in the event
-that sequence and ack numbers have been altered (as is the case for
+that sequence and ACK numbers have been altered (as in the case for
FTP data port commands).
The port numbers used by the packet aliasing module are not true
/* Local prototypes */
static int IcmpAliasIn1(struct ip *);
static int IcmpAliasIn2(struct ip *);
-static int IcmpAliasIn3(struct ip *);
static int IcmpAliasIn (struct ip *);
static int IcmpAliasOut1(struct ip *);
static int IcmpAliasOut2(struct ip *);
-static int IcmpAliasOut3(struct ip *);
static int IcmpAliasOut (struct ip *);
+static int ProtoAliasIn(struct ip *);
+static int ProtoAliasOut(struct ip *);
+
static int UdpAliasOut(struct ip *);
static int UdpAliasIn (struct ip *);
IcmpAliasIn1(struct ip *pip)
{
/*
- De-alias incoming echo and timestamp replies
+ De-alias incoming echo and timestamp replies.
+ Alias incoming echo and timestamp requests.
*/
struct alias_link *link;
struct icmp *ic;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
/* Get source address from ICMP data field and restore original data */
- link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id);
+ link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
if (link != NULL)
{
u_short original_id;
/* Adjust ICMP checksum */
accumulate = ic->icmp_id;
accumulate -= original_id;
- ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
/* Put original sequence number back in */
ic->icmp_id = original_id;
struct alias_link *link;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
- ip = (struct ip *) ic->icmp_data;
+ ip = &ic->icmp_ip;
ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
tc = (struct tcphdr *) ud;
if (ip->ip_p == IPPROTO_UDP)
link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
ud->uh_dport, ud->uh_sport,
- IPPROTO_UDP);
+ IPPROTO_UDP, 0);
else if (ip->ip_p == IPPROTO_TCP)
link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
tc->th_dport, tc->th_sport,
- IPPROTO_TCP);
+ IPPROTO_TCP, 0);
else if (ip->ip_p == IPPROTO_ICMP) {
if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
- link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id);
- else
+ link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
+ else
link = NULL;
} else
link = NULL;
accumulate -= *sptr;
accumulate += ud->uh_sport;
accumulate -= original_port;
- ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
/* Un-alias address in IP header */
DifferentialChecksum(&pip->ip_sum,
ip->ip_src = original_address;
ud->uh_sport = original_port;
}
- else if (pip->ip_p == IPPROTO_ICMP)
+ else if (ip->ip_p == IPPROTO_ICMP)
{
u_short *sptr;
int accumulate;
accumulate -= *sptr;
accumulate += ic2->icmp_id;
accumulate -= original_id;
- ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
/* Un-alias address in IP header */
DifferentialChecksum(&pip->ip_sum,
2);
pip->ip_dst = original_address;
-/* Un-alias address of original IP packet and seqence number of
- embedded icmp datagram */
+/* Un-alias address of original IP packet and sequence number of
+ embedded ICMP datagram */
ip->ip_src = original_address;
ic2->icmp_id = original_id;
}
return(PKT_ALIAS_IGNORED);
}
-static int
-IcmpAliasIn3(struct ip *pip)
-{
- struct in_addr original_address;
-
- original_address = FindOriginalAddress(pip->ip_dst);
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &original_address,
- (u_short *) &pip->ip_dst,
- 2);
- pip->ip_dst = original_address;
-
- return PKT_ALIAS_OK;
-}
-
static int
IcmpAliasIn(struct ip *pip)
break;
case ICMP_ECHO:
case ICMP_TSTAMP:
- iresult = IcmpAliasIn3(pip);
+ iresult = IcmpAliasIn1(pip);
break;
}
return(iresult);
IcmpAliasOut1(struct ip *pip)
{
/*
- Alias ICMP echo and timestamp packets
+ Alias outgoing echo and timestamp requests.
+ De-alias outgoing echo and timestamp replies.
*/
struct alias_link *link;
struct icmp *ic;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
/* Save overwritten data for when echo packet returns */
- link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id);
+ link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
if (link != NULL)
{
u_short alias_id;
/* Since data field is being modified, adjust ICMP checksum */
accumulate = ic->icmp_id;
accumulate -= alias_id;
- ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
/* Alias sequence number */
ic->icmp_id = alias_id;
Alias outgoing ICMP error messages containing
IP header and first 64 bits of datagram.
*/
- struct in_addr alias_addr;
struct ip *ip;
- struct icmp *ic;
+ struct icmp *ic, *ic2;
+ struct udphdr *ud;
+ struct tcphdr *tc;
+ struct alias_link *link;
ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
- ip = (struct ip *) ic->icmp_data;
+ ip = &ic->icmp_ip;
- alias_addr = FindAliasAddress(ip->ip_src);
-
-/* Alias destination address in IP fragment */
- DifferentialChecksum(&ic->icmp_cksum,
- (u_short *) &alias_addr,
- (u_short *) &ip->ip_dst,
- 2);
- ip->ip_dst = alias_addr;
+ ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
+ tc = (struct tcphdr *) ud;
+ ic2 = (struct icmp *) ud;
-/* alias source address in IP header */
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_addr,
- (u_short *) &pip->ip_src,
- 2);
- pip->ip_src = alias_addr;
+ if (ip->ip_p == IPPROTO_UDP)
+ link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
+ ud->uh_dport, ud->uh_sport,
+ IPPROTO_UDP, 0);
+ else if (ip->ip_p == IPPROTO_TCP)
+ link = FindUdpTcpOut(ip->ip_dst, ip->ip_src,
+ tc->th_dport, tc->th_sport,
+ IPPROTO_TCP, 0);
+ else if (ip->ip_p == IPPROTO_ICMP) {
+ if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
+ link = FindIcmpOut(ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
+ else
+ link = NULL;
+ } else
+ link = NULL;
- return PKT_ALIAS_OK;
-}
+ if (link != NULL)
+ {
+ if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
+ {
+ u_short *sptr;
+ int accumulate;
+ struct in_addr alias_address;
+ u_short alias_port;
+ alias_address = GetAliasAddress(link);
+ alias_port = GetAliasPort(link);
+
+/* Adjust ICMP checksum */
+ sptr = (u_short *) &(ip->ip_dst);
+ accumulate = *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &alias_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ accumulate += ud->uh_dport;
+ accumulate -= alias_port;
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
-static int
-IcmpAliasOut3(struct ip *pip)
-{
/*
- Handle outgoing echo and timestamp replies. The
- only thing which is done in this case is to alias
- the source IP address of the packet.
-*/
- struct in_addr alias_addr;
+ * Alias address in IP header if it comes from the host
+ * the original TCP/UDP packet was destined for.
+ */
+ if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_address,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_address;
+ }
+
+/* Alias address and port number of original IP packet
+fragment contained in ICMP data section */
+ ip->ip_dst = alias_address;
+ ud->uh_dport = alias_port;
+ }
+ else if (ip->ip_p == IPPROTO_ICMP)
+ {
+ u_short *sptr;
+ int accumulate;
+ struct in_addr alias_address;
+ u_short alias_id;
- alias_addr = FindAliasAddress(pip->ip_src);
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_addr,
- (u_short *) &pip->ip_src,
- 2);
- pip->ip_src = alias_addr;
+ alias_address = GetAliasAddress(link);
+ alias_id = GetAliasPort(link);
+
+/* Adjust ICMP checksum */
+ sptr = (u_short *) &(ip->ip_dst);
+ accumulate = *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &alias_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ accumulate += ic2->icmp_id;
+ accumulate -= alias_id;
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
- return PKT_ALIAS_OK;
+/*
+ * Alias address in IP header if it comes from the host
+ * the original ICMP message was destined for.
+ */
+ if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_address,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_address;
+ }
+
+/* Alias address of original IP packet and sequence number of
+ embedded ICMP datagram */
+ ip->ip_dst = alias_address;
+ ic2->icmp_id = alias_id;
+ }
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
}
break;
case ICMP_ECHOREPLY:
case ICMP_TSTAMPREPLY:
- iresult = IcmpAliasOut3(pip);
+ iresult = IcmpAliasOut1(pip);
}
return(iresult);
}
static int
-PptpAliasIn(struct ip *pip)
+ProtoAliasIn(struct ip *pip)
{
/*
- Handle incoming PPTP packets. The
+ Handle incoming IP 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;
+ struct alias_link *link;
- if (!GetPptpAlias (&alias_addr))
- return PKT_ALIAS_IGNORED;
+/* Return if proxy-only mode is enabled */
+ if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
+ return PKT_ALIAS_OK;
- if (pip->ip_src.s_addr != alias_addr.s_addr) {
+ link = FindProtoIn(pip->ip_src, pip->ip_dst, pip->ip_p);
+ if (link != NULL)
+ {
+ struct in_addr original_address;
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_addr,
- (u_short *) &pip->ip_dst,
- 2);
- pip->ip_dst = alias_addr;
- }
+ original_address = GetOriginalAddress(link);
+
+/* Restore original IP address */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_dst,
+ 2);
+ pip->ip_dst = original_address;
- return PKT_ALIAS_OK;
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
}
static int
-PptpAliasOut(struct ip *pip)
+ProtoAliasOut(struct ip *pip)
{
/*
- Handle outgoing PPTP packets. The
+ Handle outgoing IP 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;
+ struct alias_link *link;
- if (!GetPptpAlias (&alias_addr))
- return PKT_ALIAS_IGNORED;
+/* Return if proxy-only mode is enabled */
+ if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
+ return PKT_ALIAS_OK;
- if (pip->ip_src.s_addr == alias_addr.s_addr) {
+ link = FindProtoOut(pip->ip_src, pip->ip_dst, pip->ip_p);
+ if (link != NULL)
+ {
+ struct in_addr alias_address;
- 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;
- }
+ alias_address = GetAliasAddress(link);
- return PKT_ALIAS_OK;
-}
+/* Change source address */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &alias_address,
+ (u_short *) &pip->ip_src,
+ 2);
+ pip->ip_src = alias_address;
+ return(PKT_ALIAS_OK);
+ }
+ return(PKT_ALIAS_IGNORED);
+}
static int
link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
ud->uh_sport, ud->uh_dport,
- IPPROTO_UDP);
+ IPPROTO_UDP, 1);
if (link != NULL)
{
struct in_addr alias_address;
alias_port = ud->uh_dport;
ud->uh_dport = GetOriginalPort(link);
+/* Special processing for IP encoding protocols */
+ if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
+ AliasHandleCUSeeMeIn(pip, original_address);
/* If NETBIOS Datagram, It should be alias address in UDP Data, too */
- if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
- || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
- {
- r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
- } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
- || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER )
- {
- r = AliasHandleUdpNbtNS(pip, link,
- &alias_address,
- &alias_port,
- &original_address,
- &ud->uh_dport );
- }
-
- if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
- AliasHandleCUSeeMeIn(pip, original_address);
+ else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
+ || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
+ r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
+ else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
+ || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
+ r = AliasHandleUdpNbtNS(pip, link, &alias_address, &alias_port,
+ &original_address, &ud->uh_dport);
/* If UDP checksum is not zero, then adjust since destination port */
-/* is being unaliased and destination port is being altered. */
+/* is being unaliased and destination address is being altered. */
if (ud->uh_sum != 0)
{
accumulate = alias_port;
sptr = (u_short *) &original_address;
accumulate -= *sptr++;
accumulate -= *sptr;
- ADJUST_CHECKSUM(accumulate, ud->uh_sum)
+ ADJUST_CHECKSUM(accumulate, ud->uh_sum);
}
/* Restore original IP address */
link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
ud->uh_sport, ud->uh_dport,
- IPPROTO_UDP);
+ IPPROTO_UDP, 1);
if (link != NULL)
{
u_short alias_port;
alias_address = GetAliasAddress(link);
alias_port = GetAliasPort(link);
- if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
- AliasHandleCUSeeMeOut(pip, link);
-
+/* Special processing for IP encoding protocols */
+ if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
+ AliasHandleCUSeeMeOut(pip, link);
/* If NETBIOS Datagram, It should be alias address in UDP Data, too */
- if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
- || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
- {
- AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
- } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
- || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER )
- {
- AliasHandleUdpNbtNS(pip, link,
- &pip->ip_src,
- &ud->uh_sport,
- &alias_address,
- &alias_port);
- }
+ else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
+ || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
+ AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
+ else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
+ || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
+ AliasHandleUdpNbtNS(pip, link, &pip->ip_src, &ud->uh_sport,
+ &alias_address, &alias_port);
/* If UDP checksum is not zero, adjust since source port is */
/* being aliased and source address is being altered */
sptr = (u_short *) &alias_address;
accumulate -= *sptr++;
accumulate -= *sptr;
- ADJUST_CHECKSUM(accumulate, ud->uh_sum)
+ ADJUST_CHECKSUM(accumulate, ud->uh_sum);
}
/* Put alias port in UDP header */
link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
tc->th_sport, tc->th_dport,
- IPPROTO_TCP);
+ IPPROTO_TCP,
+ !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
if (link != NULL)
{
struct in_addr alias_address;
int accumulate;
u_short *sptr;
+/* Special processing for IP encoding protocols */
+ if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
+ || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
+ AliasHandlePptpIn(pip, link);
+
alias_address = GetAliasAddress(link);
original_address = GetOriginalAddress(link);
proxy_address = GetProxyAddress(link);
accumulate -= *sptr++;
accumulate -= *sptr;
-/* If this is a proxy, then modify the tcp source port and
+/* If this is a proxy, then modify the TCP source port and
checksum accumulation */
if (proxy_port != 0)
{
accumulate -= *sptr;
}
-/* See if ack number needs to be modified */
+/* See if ACK number needs to be modified */
if (GetAckModified(link) == 1)
{
int delta;
return PKT_ALIAS_OK;
/* If this is a transparent proxy, save original destination,
- then alter the destination and adust checksums */
+ then alter the destination and adjust checksums */
dest_port = tc->th_dport;
dest_address = pip->ip_dst;
if (proxy_type != 0)
link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
tc->th_sport, tc->th_dport,
- IPPROTO_TCP);
+ IPPROTO_TCP, 1);
if (link !=NULL)
{
u_short alias_port;
alias_port = GetAliasPort(link);
alias_address = GetAliasAddress(link);
-/* Monitor tcp connection state */
+/* Monitor TCP connection state */
TcpMonitorOut(pip, link);
/* 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
+ else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
|| ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
AliasHandleIrcOut(pip, link, maxpacketsize);
+ else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
+ || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
+ || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
+ || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
+ AliasHandleRtspOut(pip, link, maxpacketsize);
+ else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
+ || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
+ AliasHandlePptpOut(pip, link);
/* Adjust TCP checksum since source port is being aliased */
/* and source address is being altered */
}
}
- ADJUST_CHECKSUM(accumulate, tc->th_sum)
+ ADJUST_CHECKSUM(accumulate, tc->th_sum);
/* Change source address */
sptr = (u_short *) &(pip->ip_src);
accumulate -= *sptr++;
accumulate -= *sptr;
- ADJUST_CHECKSUM(accumulate, pip->ip_sum)
+ ADJUST_CHECKSUM(accumulate, pip->ip_sum);
return(PKT_ALIAS_OK);
}
The packet aliasing module has a limited ability for handling IP
fragments. If the ICMP, TCP or UDP header is in the first fragment
-received, then the id number of the IP packet is saved, and other
+received, then the ID number of the IP packet is saved, and other
fragments are identified according to their ID number and IP address
they were sent from. Pointers to unresolved fragments can also be
saved and recalled when a header fragment is seen.
PacketAliasFragmentIn()
PacketAliasIn()
PacketAliasOut()
+ PacketUnaliasOut()
(prototypes in alias.h)
*/
struct ip *pip;
int iresult;
- if (packetAliasMode & PKT_ALIAS_REVERSE)
- return PacketAliasOut(ptr, maxpacketsize);
+ if (packetAliasMode & PKT_ALIAS_REVERSE) {
+ packetAliasMode &= ~PKT_ALIAS_REVERSE;
+ iresult = PacketAliasOut(ptr, maxpacketsize);
+ packetAliasMode |= PKT_ALIAS_REVERSE;
+ return iresult;
+ }
HouseKeeping();
ClearCheckNewLink();
iresult = TcpAliasIn(pip);
break;
case IPPROTO_GRE:
- iresult = PptpAliasIn(pip);
+ if (packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
+ AliasHandlePptpGreIn(pip) == 0)
+ iresult = PKT_ALIAS_OK;
+ else
+ iresult = ProtoAliasIn(pip);
+ break;
+ default:
+ iresult = ProtoAliasIn(pip);
break;
}
struct in_addr addr_save;
struct ip *pip;
- if (packetAliasMode & PKT_ALIAS_REVERSE)
- return PacketAliasIn(ptr, maxpacketsize);
+ if (packetAliasMode & PKT_ALIAS_REVERSE) {
+ packetAliasMode &= ~PKT_ALIAS_REVERSE;
+ iresult = PacketAliasIn(ptr, maxpacketsize);
+ packetAliasMode |= PKT_ALIAS_REVERSE;
+ return iresult;
+ }
HouseKeeping();
ClearCheckNewLink();
addr_save = GetDefaultAliasAddress();
if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
{
- unsigned int addr;
+ in_addr_t addr;
int iclass;
iclass = 0;
case IPPROTO_TCP:
iresult = TcpAliasOut(pip, maxpacketsize);
break;
- case IPPROTO_GRE:
- iresult = PptpAliasOut(pip);
+ case IPPROTO_GRE:
+ if (AliasHandlePptpGreOut(pip) == 0)
+ iresult = PKT_ALIAS_OK;
+ else
+ iresult = ProtoAliasOut(pip);
+ break;
+ default:
+ iresult = ProtoAliasOut(pip);
break;
}
}
SetDefaultAliasAddress(addr_save);
return(iresult);
}
+
+int
+PacketUnaliasOut(char *ptr, /* valid IP packet */
+ int maxpacketsize /* for error checking */
+ )
+{
+ struct ip *pip;
+ struct icmp *ic;
+ struct udphdr *ud;
+ struct tcphdr *tc;
+ struct alias_link *link;
+ int iresult = PKT_ALIAS_IGNORED;
+
+ pip = (struct ip *) ptr;
+
+ /* Defense against mangled packets */
+ if (ntohs(pip->ip_len) > maxpacketsize
+ || (pip->ip_hl<<2) > maxpacketsize)
+ return(iresult);
+
+ ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+ tc = (struct tcphdr *) ud;
+ ic = (struct icmp *) ud;
+
+ /* Find a link */
+ if (pip->ip_p == IPPROTO_UDP)
+ link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
+ ud->uh_dport, ud->uh_sport,
+ IPPROTO_UDP, 0);
+ else if (pip->ip_p == IPPROTO_TCP)
+ link = FindUdpTcpIn(pip->ip_dst, pip->ip_src,
+ tc->th_dport, tc->th_sport,
+ IPPROTO_TCP, 0);
+ else if (pip->ip_p == IPPROTO_ICMP)
+ link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
+ else
+ link = NULL;
+
+ /* Change it from an aliased packet to an unaliased packet */
+ if (link != NULL)
+ {
+ if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP)
+ {
+ u_short *sptr;
+ int accumulate;
+ struct in_addr original_address;
+ u_short original_port;
+
+ original_address = GetOriginalAddress(link);
+ original_port = GetOriginalPort(link);
+
+ /* Adjust TCP/UDP checksum */
+ sptr = (u_short *) &(pip->ip_src);
+ accumulate = *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &original_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+
+ if (pip->ip_p == IPPROTO_UDP) {
+ accumulate += ud->uh_sport;
+ accumulate -= original_port;
+ ADJUST_CHECKSUM(accumulate, ud->uh_sum);
+ } else {
+ accumulate += tc->th_sport;
+ accumulate -= original_port;
+ ADJUST_CHECKSUM(accumulate, tc->th_sum);
+ }
+
+ /* Adjust IP checksum */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_src,
+ 2);
+
+ /* Un-alias source address and port number */
+ pip->ip_src = original_address;
+ if (pip->ip_p == IPPROTO_UDP)
+ ud->uh_sport = original_port;
+ else
+ tc->th_sport = original_port;
+
+ iresult = PKT_ALIAS_OK;
+
+ } else if (pip->ip_p == IPPROTO_ICMP) {
+
+ u_short *sptr;
+ int accumulate;
+ struct in_addr original_address;
+ u_short original_id;
+
+ original_address = GetOriginalAddress(link);
+ original_id = GetOriginalPort(link);
+
+ /* Adjust ICMP checksum */
+ sptr = (u_short *) &(pip->ip_src);
+ accumulate = *sptr++;
+ accumulate += *sptr;
+ sptr = (u_short *) &original_address;
+ accumulate -= *sptr++;
+ accumulate -= *sptr;
+ accumulate += ic->icmp_id;
+ accumulate -= original_id;
+ ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
+
+ /* Adjust IP checksum */
+ DifferentialChecksum(&pip->ip_sum,
+ (u_short *) &original_address,
+ (u_short *) &pip->ip_src,
+ 2);
+
+ /* Un-alias source address and port number */
+ pip->ip_src = original_address;
+ ic->icmp_id = original_id;
+
+ iresult = PKT_ALIAS_OK;
+ }
+ }
+ return(iresult);
+
+}