Added true support for PPTP aliasing. Some nice features include:
- Multiple PPTP clients behind NAT to the same or different servers. - Single PPTP server behind NAT -- you just need to redirect TCP port 1723 to a local machine. Multiple servers behind NAT is possible but would require a simple API change. - No API changes! For more information on how this works see comments at the start of the alias_pptp.c. PacketAliasPptp() is no longer necessary and will be removed soon. Submitted by: Erik Salander <erik@whistle.com> Reviewed by: ru Rewritten by: ru Reviewed by: Erik Salander <erik@whistle.com>
This commit is contained in:
parent
953ae31a00
commit
55a39fc5a2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=61861
@ -134,3 +134,8 @@ Version 3.0: January 1, 1999
|
||||
- Transparent proxying support added.
|
||||
- PPTP redirecting support added based on patches
|
||||
contributed by Dru Nelson <dnelson@redwoodsoft.com>.
|
||||
|
||||
Version 3.1: May, 2000 (Erik Salander, erik@whistle.com)
|
||||
- Added support to alias 227 replies, allows aliasing for
|
||||
FTP servers in passive mode.
|
||||
- Added support for PPTP aliasing.
|
||||
|
@ -5,7 +5,7 @@ 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_proxy.c alias_util.c
|
||||
alias_nbt.c alias_pptp.c alias_proxy.c alias_util.c
|
||||
INCS= alias.h
|
||||
MAN3= libalias.3
|
||||
|
||||
|
@ -76,6 +76,9 @@
|
||||
Version 2.3 Dec 1998 (dillon)
|
||||
- Major bounds checking additions, see FreeBSD/CVS
|
||||
|
||||
Version 3.1 May, 2000 (eds)
|
||||
- Added hooks to handle PPTP.
|
||||
|
||||
See HISTORY file for additional revisions.
|
||||
|
||||
$FreeBSD$
|
||||
@ -90,12 +93,6 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#ifndef IPPROTO_GRE
|
||||
#define IPPROTO_GRE 47
|
||||
#define IPPROTO_ESP 50
|
||||
#define IPPROTO_AH 51
|
||||
#endif
|
||||
|
||||
#include "alias_local.h"
|
||||
#include "alias.h"
|
||||
|
||||
@ -105,6 +102,7 @@
|
||||
#define IRC_CONTROL_PORT_NUMBER_1 6667
|
||||
#define IRC_CONTROL_PORT_NUMBER_2 6668
|
||||
#define CUSEEME_PORT_NUMBER 7648
|
||||
#define PPTP_CONTROL_PORT_NUMBER 1723
|
||||
|
||||
|
||||
|
||||
@ -181,6 +179,7 @@ TcpMonitorOut(struct ip *pip, struct alias_link *link)
|
||||
ProtoAliasIn(), ProtoAliasOut()
|
||||
UdpAliasIn(), UdpAliasOut()
|
||||
TcpAliasIn(), TcpAliasOut()
|
||||
GreAliasIn()
|
||||
|
||||
These routines handle protocol specific details of packet aliasing.
|
||||
One may observe a certain amount of repetitive arithmetic in these
|
||||
@ -234,6 +233,8 @@ static int UdpAliasIn (struct ip *);
|
||||
static int TcpAliasOut(struct ip *, int);
|
||||
static int TcpAliasIn (struct ip *);
|
||||
|
||||
static int GreAliasIn(struct ip *);
|
||||
|
||||
|
||||
static int
|
||||
IcmpAliasIn1(struct ip *pip)
|
||||
@ -725,6 +726,39 @@ ProtoAliasOut(struct ip *pip)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
GreAliasIn(struct ip *pip)
|
||||
{
|
||||
u_short call_id;
|
||||
struct alias_link *link;
|
||||
|
||||
/* Return if proxy-only mode is enabled. */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return (PKT_ALIAS_OK);
|
||||
|
||||
if (PptpGetCallID(pip, &call_id)) {
|
||||
if ((link = FindPptpIn(pip->ip_src, pip->ip_dst, call_id)) != NULL) {
|
||||
struct in_addr alias_address;
|
||||
struct in_addr original_address;
|
||||
|
||||
alias_address = GetAliasAddress(link);
|
||||
original_address = GetOriginalAddress(link);
|
||||
PptpSetCallID(pip, GetOriginalPort(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);
|
||||
} else
|
||||
return (PKT_ALIAS_IGNORED);
|
||||
} else
|
||||
return ProtoAliasIn(pip);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
UdpAliasIn(struct ip *pip)
|
||||
@ -903,6 +937,11 @@ TcpAliasIn(struct ip *pip)
|
||||
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);
|
||||
@ -1070,9 +1109,12 @@ TcpAliasOut(struct ip *pip, int maxpacketsize)
|
||||
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) == 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 */
|
||||
@ -1301,6 +1343,9 @@ PacketAliasIn(char *ptr, int maxpacketsize)
|
||||
case IPPROTO_TCP:
|
||||
iresult = TcpAliasIn(pip);
|
||||
break;
|
||||
case IPPROTO_GRE:
|
||||
iresult = GreAliasIn(pip);
|
||||
break;
|
||||
default:
|
||||
iresult = ProtoAliasIn(pip);
|
||||
break;
|
||||
|
@ -147,6 +147,7 @@
|
||||
/* Timeouts (in seconds) for different link types */
|
||||
#define ICMP_EXPIRE_TIME 60
|
||||
#define UDP_EXPIRE_TIME 60
|
||||
#define PPTP_EXPIRE_TIME 60
|
||||
#define PROTO_EXPIRE_TIME 60
|
||||
#define FRAGMENT_ID_EXPIRE_TIME 10
|
||||
#define FRAGMENT_PTR_EXPIRE_TIME 30
|
||||
@ -265,6 +266,7 @@ struct alias_link /* Main data structure */
|
||||
#define LINK_FRAGMENT_ID (IPPROTO_MAX + 1)
|
||||
#define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2)
|
||||
#define LINK_ADDR (IPPROTO_MAX + 3)
|
||||
#define LINK_PPTP (IPPROTO_MAX + 4)
|
||||
|
||||
int flags; /* indicates special characteristics */
|
||||
|
||||
@ -329,6 +331,7 @@ linkTableIn[LINK_TABLE_IN_SIZE]; /* into input and output lookup */
|
||||
static int icmpLinkCount; /* Link statistics */
|
||||
static int udpLinkCount;
|
||||
static int tcpLinkCount;
|
||||
static int pptpLinkCount;
|
||||
static int protoLinkCount;
|
||||
static int fragmentIdLinkCount;
|
||||
static int fragmentPtrLinkCount;
|
||||
@ -455,10 +458,11 @@ ShowAliasStats(void)
|
||||
|
||||
if (monitorFile)
|
||||
{
|
||||
fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, proto=%d, frag_id=%d frag_ptr=%d",
|
||||
fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, pptp=%d, proto=%d, frag_id=%d frag_ptr=%d",
|
||||
icmpLinkCount,
|
||||
udpLinkCount,
|
||||
tcpLinkCount,
|
||||
pptpLinkCount,
|
||||
protoLinkCount,
|
||||
fragmentIdLinkCount,
|
||||
fragmentPtrLinkCount);
|
||||
@ -466,6 +470,7 @@ ShowAliasStats(void)
|
||||
fprintf(monitorFile, " / tot=%d (sock=%d)\n",
|
||||
icmpLinkCount + udpLinkCount
|
||||
+ tcpLinkCount
|
||||
+ pptpLinkCount
|
||||
+ protoLinkCount
|
||||
+ fragmentIdLinkCount
|
||||
+ fragmentPtrLinkCount,
|
||||
@ -550,7 +555,7 @@ GetNewPort(struct alias_link *link, int alias_port_param)
|
||||
the port number. GetNewPort() will return this number
|
||||
without check that it is in use.
|
||||
|
||||
When this parameter is -1, it indicates to get a randomly
|
||||
When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
|
||||
selected port number.
|
||||
*/
|
||||
|
||||
@ -618,7 +623,9 @@ GetNewPort(struct alias_link *link, int alias_port_param)
|
||||
if (go_ahead)
|
||||
{
|
||||
if ((packetAliasMode & PKT_ALIAS_USE_SOCKETS)
|
||||
&& (link->flags & LINK_PARTIALLY_SPECIFIED))
|
||||
&& (link->flags & LINK_PARTIALLY_SPECIFIED)
|
||||
&& ((link->link_type == LINK_TCP) ||
|
||||
(link->link_type == LINK_UDP)))
|
||||
{
|
||||
if (GetSocket(port_net, &link->sockfd, link->link_type))
|
||||
{
|
||||
@ -838,6 +845,9 @@ DeleteLink(struct alias_link *link)
|
||||
if (link->data.tcp != NULL)
|
||||
free(link->data.tcp);
|
||||
break;
|
||||
case LINK_PPTP:
|
||||
pptpLinkCount--;
|
||||
break;
|
||||
case LINK_FRAGMENT_ID:
|
||||
fragmentIdLinkCount--;
|
||||
break;
|
||||
@ -906,6 +916,9 @@ AddLink(struct in_addr src_addr,
|
||||
case LINK_TCP:
|
||||
link->expire_time = TCP_EXPIRE_INITIAL;
|
||||
break;
|
||||
case LINK_PPTP:
|
||||
link->expire_time = PPTP_EXPIRE_TIME;
|
||||
break;
|
||||
case LINK_FRAGMENT_ID:
|
||||
link->expire_time = FRAGMENT_ID_EXPIRE_TIME;
|
||||
break;
|
||||
@ -994,6 +1007,9 @@ AddLink(struct in_addr src_addr,
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case LINK_PPTP:
|
||||
pptpLinkCount++;
|
||||
break;
|
||||
case LINK_FRAGMENT_ID:
|
||||
fragmentIdLinkCount++;
|
||||
break;
|
||||
@ -1307,6 +1323,7 @@ FindLinkIn(struct in_addr dst_addr,
|
||||
AddFragmentPtrLink(), FindFragmentPtr()
|
||||
FindProtoIn(), FindProtoOut()
|
||||
FindUdpTcpIn(), FindUdpTcpOut()
|
||||
FindPptpIn(), FindPptpOut()
|
||||
FindOriginalAddress(), FindAliasAddress()
|
||||
|
||||
(prototypes in alias_local.h)
|
||||
@ -1533,6 +1550,56 @@ FindUdpTcpOut(struct in_addr src_addr,
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
FindPptpIn(struct in_addr dst_addr,
|
||||
struct in_addr alias_addr,
|
||||
u_short call_id)
|
||||
{
|
||||
struct alias_link *link;
|
||||
|
||||
link = FindLinkIn(dst_addr, alias_addr,
|
||||
NO_DEST_PORT, call_id,
|
||||
LINK_PPTP, 1);
|
||||
|
||||
if (link == NULL && !(packetAliasMode & PKT_ALIAS_DENY_INCOMING))
|
||||
{
|
||||
struct in_addr target_addr;
|
||||
|
||||
target_addr = FindOriginalAddress(alias_addr);
|
||||
link = AddLink(target_addr, dst_addr, alias_addr,
|
||||
call_id, NO_DEST_PORT, call_id,
|
||||
LINK_PPTP);
|
||||
}
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
FindPptpOut(struct in_addr src_addr,
|
||||
struct in_addr dst_addr,
|
||||
u_short call_id)
|
||||
{
|
||||
struct alias_link *link;
|
||||
|
||||
link = FindLinkOut(src_addr, dst_addr,
|
||||
call_id, NO_DEST_PORT,
|
||||
LINK_PPTP, 1);
|
||||
|
||||
if (link == NULL)
|
||||
{
|
||||
struct in_addr alias_addr;
|
||||
|
||||
alias_addr = FindAliasAddress(src_addr);
|
||||
link = AddLink(src_addr, dst_addr, alias_addr,
|
||||
call_id, NO_DEST_PORT, GET_ALIAS_PORT,
|
||||
LINK_PPTP);
|
||||
}
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct in_addr alias_addr)
|
||||
{
|
||||
@ -2308,6 +2375,7 @@ PacketAliasInit(void)
|
||||
icmpLinkCount = 0;
|
||||
udpLinkCount = 0;
|
||||
tcpLinkCount = 0;
|
||||
pptpLinkCount = 0;
|
||||
protoLinkCount = 0;
|
||||
fragmentIdLinkCount = 0;
|
||||
fragmentPtrLinkCount = 0;
|
||||
|
@ -107,6 +107,12 @@ FindUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
struct alias_link *
|
||||
FindUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
|
||||
struct alias_link *
|
||||
FindPptpIn(struct in_addr, struct in_addr, u_short);
|
||||
|
||||
struct alias_link *
|
||||
FindPptpOut(struct in_addr, struct in_addr, u_short);
|
||||
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct in_addr);
|
||||
|
||||
@ -159,6 +165,12 @@ void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
|
||||
/* IRC routines */
|
||||
void AliasHandleIrcOut(struct ip *, struct alias_link *, int);
|
||||
|
||||
/* PPTP routines */
|
||||
int PptpGetCallID(struct ip *, u_short *);
|
||||
void PptpSetCallID(struct ip *, u_short);
|
||||
void AliasHandlePptpOut(struct ip *, struct alias_link *);
|
||||
void AliasHandlePptpIn(struct ip *, struct alias_link *);
|
||||
|
||||
/* 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 *);
|
||||
|
279
lib/libalias/alias_pptp.c
Normal file
279
lib/libalias/alias_pptp.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* alias_pptp.c
|
||||
*
|
||||
* Copyright (c) 2000 Whistle Communications, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Subject to the following obligations and disclaimer of warranty, use and
|
||||
* redistribution of this software, in source or object code forms, with or
|
||||
* without modifications are expressly permitted by Whistle Communications;
|
||||
* provided, however, that:
|
||||
* 1. Any and all reproductions of the source or object code must include the
|
||||
* copyright notice above and the following disclaimer of warranties; and
|
||||
* 2. No rights are granted, in any manner or form, to use Whistle
|
||||
* Communications, Inc. trademarks, including the mark "WHISTLE
|
||||
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
|
||||
* such appears in the above copyright notice or in the software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
|
||||
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
|
||||
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
|
||||
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
|
||||
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
|
||||
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
|
||||
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
|
||||
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Erik Salander <erik@whistle.com>
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
Alias_pptp.c performs special processing for PPTP sessions under TCP.
|
||||
Specifically, watch PPTP control messages and alias the Call ID or the
|
||||
Peer's Call ID in the appropriate messages. Note, PPTP requires
|
||||
"de-aliasing" of incoming packets, this is different than any other
|
||||
TCP applications that are currently (ie. FTP, IRC and RTSP) aliased.
|
||||
|
||||
For Call IDs encountered for the first time, a GRE alias link is created.
|
||||
The GRE alias link uses the Call ID in place of the original port number.
|
||||
An alias Call ID is created.
|
||||
|
||||
For this routine to work, the PPTP control messages must fit entirely
|
||||
into a single TCP packet. This is typically the case, but is not
|
||||
required by the spec.
|
||||
|
||||
Unlike some of the other TCP applications that are aliased (ie. FTP,
|
||||
IRC and RTSP), the PPTP control messages that need to be aliased are
|
||||
guaranteed to remain the same length. The aliased Call ID is a fixed
|
||||
length field.
|
||||
|
||||
Reference: RFC 2637
|
||||
|
||||
Initial version: May, 2000 (eds)
|
||||
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
/*
|
||||
* PPTP definitions
|
||||
*/
|
||||
|
||||
struct grehdr /* Enhanced GRE header. */
|
||||
{
|
||||
u_char gh_recursion:3, /* Recursion control. */
|
||||
gh_ssr_flag:1, /* Strict source route present. */
|
||||
gh_seq_no_flag:1, /* Sequence number present. */
|
||||
gh_key_flag:1, /* Key present. */
|
||||
gh_rt_flag:1, /* Routing present. */
|
||||
gh_cksum_flag:1; /* Checksum present. */
|
||||
u_char gh_version:3, /* GRE version. */
|
||||
gh_flags:4, /* Flags. */
|
||||
gh_ack_no_flag:1; /* Acknowledgment sequence number present. */
|
||||
u_short gh_protocol; /* Protocol type. */
|
||||
u_short gh_length; /* Payload length. */
|
||||
u_short gh_call_id; /* Call ID. */
|
||||
u_int32_t gh_seq_no; /* Sequence number (optional). */
|
||||
u_int32_t gh_ack_no; /* Acknowledgment number (optional). */
|
||||
};
|
||||
|
||||
/* The PPTP protocol ID used in the GRE 'proto' field. */
|
||||
#define PPTP_GRE_PROTO 0x880b
|
||||
|
||||
/* Bits that must be set a certain way in all PPTP/GRE packets. */
|
||||
#define PPTP_INIT_VALUE ((0x2001 << 16) | PPTP_GRE_PROTO)
|
||||
#define PPTP_INIT_MASK 0xef7fffff
|
||||
|
||||
#define PPTP_MAGIC 0x1a2b3c4d
|
||||
#define PPTP_CTRL_MSG_TYPE 1
|
||||
|
||||
enum {
|
||||
PPTP_StartCtrlConnRequest = 1,
|
||||
PPTP_StartCtrlConnReply = 2,
|
||||
PPTP_StopCtrlConnRequest = 3,
|
||||
PPTP_StopCtrlConnReply = 4,
|
||||
PPTP_EchoRequest = 5,
|
||||
PPTP_statoReply = 6,
|
||||
PPTP_OutCallRequest = 7,
|
||||
PPTP_OutCallReply = 8,
|
||||
PPTP_InCallRequest = 9,
|
||||
PPTP_InCallReply = 10,
|
||||
PPTP_InCallConn = 11,
|
||||
PPTP_CallClearRequest = 12,
|
||||
PPTP_CallDiscNotify = 13,
|
||||
PPTP_WanErrorNotify = 14,
|
||||
PPTP_SetLinkInfo = 15,
|
||||
};
|
||||
|
||||
/* Message structures */
|
||||
struct pptpMsgHead {
|
||||
u_int16_t length; /* total length */
|
||||
u_int16_t msgType; /* PPTP message type */
|
||||
u_int32_t magic; /* magic cookie */
|
||||
u_int16_t type; /* control message type */
|
||||
u_int16_t resv0; /* reserved */
|
||||
};
|
||||
typedef struct pptpMsgHead *PptpMsgHead;
|
||||
|
||||
struct pptpCallIds {
|
||||
u_int16_t cid1; /* Call ID field #1 */
|
||||
u_int16_t cid2; /* Call ID field #2 */
|
||||
};
|
||||
typedef struct pptpCallIds *PptpCallId;
|
||||
|
||||
static PptpCallId AliasVerifyPptp(struct ip *, u_int16_t *);
|
||||
|
||||
int
|
||||
PptpGetCallID(struct ip *pip,
|
||||
u_short *call_id)
|
||||
{
|
||||
struct grehdr *gr;
|
||||
|
||||
gr = (struct grehdr *)((char *)pip + (pip->ip_hl << 2));
|
||||
|
||||
/* Check GRE header bits. */
|
||||
if ((ntohl(*((u_int32_t *)gr)) & PPTP_INIT_MASK) == PPTP_INIT_VALUE) {
|
||||
*call_id = gr->gh_call_id;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
};
|
||||
|
||||
void PptpSetCallID(struct ip *pip, u_short call_id)
|
||||
{
|
||||
struct grehdr *gr;
|
||||
|
||||
gr = (struct grehdr *)((char *)pip + (pip->ip_hl << 2));
|
||||
gr->gh_call_id = call_id;
|
||||
};
|
||||
|
||||
void
|
||||
AliasHandlePptpOut(struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *link) /* The PPTP control link */
|
||||
{
|
||||
struct alias_link *gre_link;
|
||||
PptpCallId cptr;
|
||||
u_int16_t ctl_type; /* control message type */
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Verify valid PPTP control message */
|
||||
if ((cptr = AliasVerifyPptp(pip, &ctl_type)) == NULL)
|
||||
return;
|
||||
|
||||
/* Modify certain PPTP messages */
|
||||
if ((ctl_type >= PPTP_OutCallRequest) &&
|
||||
(ctl_type <= PPTP_CallDiscNotify)) {
|
||||
|
||||
/* Establish GRE link for address and Call ID found in PPTP Control Msg */
|
||||
gre_link = FindPptpOut(GetOriginalAddress(link), GetDestAddress(link),
|
||||
cptr->cid1);
|
||||
|
||||
if (gre_link != NULL) {
|
||||
/* alias the Call Id */
|
||||
cptr->cid1 = GetAliasPort(gre_link);
|
||||
|
||||
/* Compute TCP checksum for revised packet */
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AliasHandlePptpIn(struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *link) /* The PPTP control link */
|
||||
{
|
||||
struct alias_link *gre_link;
|
||||
PptpCallId cptr;
|
||||
u_int16_t *pcall_id;
|
||||
u_int16_t ctl_type; /* control message type */
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Verify valid PPTP control message */
|
||||
if ((cptr = AliasVerifyPptp(pip, &ctl_type)) == NULL)
|
||||
return;
|
||||
|
||||
/* Modify certain PPTP messages */
|
||||
switch (ctl_type)
|
||||
{
|
||||
case PPTP_InCallConn:
|
||||
case PPTP_WanErrorNotify:
|
||||
case PPTP_SetLinkInfo:
|
||||
pcall_id = &cptr->cid1;
|
||||
break;
|
||||
case PPTP_OutCallReply:
|
||||
case PPTP_InCallReply:
|
||||
pcall_id = &cptr->cid2;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find GRE link for address and Call ID found in PPTP Control Msg */
|
||||
gre_link = FindPptpIn(GetDestAddress(link), GetAliasAddress(link),
|
||||
*pcall_id);
|
||||
|
||||
if (gre_link != NULL) {
|
||||
/* alias the Call Id */
|
||||
*pcall_id = GetOriginalPort(gre_link);
|
||||
|
||||
/* Compute TCP checksum for modified packet */
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
}
|
||||
}
|
||||
|
||||
PptpCallId
|
||||
AliasVerifyPptp(struct ip *pip, u_int16_t *ptype) /* IP packet to examine/patch */
|
||||
{
|
||||
int hlen, tlen, dlen;
|
||||
PptpMsgHead hptr;
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Calculate some lengths */
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
tlen = ntohs(pip->ip_len);
|
||||
dlen = tlen - hlen;
|
||||
|
||||
/* Verify data length */
|
||||
if (dlen < (sizeof(struct pptpMsgHead) + sizeof(struct pptpCallIds)))
|
||||
return(NULL);
|
||||
|
||||
/* Move up to PPTP message header */
|
||||
hptr = (PptpMsgHead)(((char *) pip) + hlen);
|
||||
|
||||
/* Return the control message type */
|
||||
*ptype = ntohs(hptr->type);
|
||||
|
||||
/* Verify PPTP Control Message */
|
||||
if ((ntohs(hptr->msgType) != PPTP_CTRL_MSG_TYPE) ||
|
||||
(ntohl(hptr->magic) != PPTP_MAGIC))
|
||||
return(NULL);
|
||||
else
|
||||
return((PptpCallId)(((char *)hptr) + sizeof(struct pptpMsgHead)));
|
||||
}
|
@ -835,6 +835,8 @@ versions 1.0 - 1.8, 2.0 - 2.4.
|
||||
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.
|
||||
.An Erik Salander Aq erik@whistle.com
|
||||
added support for PPTP.
|
||||
.Sh ACKNOWLEDGMENTS
|
||||
Listed below, in approximate chronological order, are individuals who
|
||||
have provided valuable comments and/or debugging assistance.
|
||||
|
@ -134,3 +134,8 @@ Version 3.0: January 1, 1999
|
||||
- Transparent proxying support added.
|
||||
- PPTP redirecting support added based on patches
|
||||
contributed by Dru Nelson <dnelson@redwoodsoft.com>.
|
||||
|
||||
Version 3.1: May, 2000 (Erik Salander, erik@whistle.com)
|
||||
- Added support to alias 227 replies, allows aliasing for
|
||||
FTP servers in passive mode.
|
||||
- Added support for PPTP aliasing.
|
||||
|
@ -5,7 +5,7 @@ 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_proxy.c alias_util.c
|
||||
alias_nbt.c alias_pptp.c alias_proxy.c alias_util.c
|
||||
INCS= alias.h
|
||||
MAN3= libalias.3
|
||||
|
||||
|
@ -76,6 +76,9 @@
|
||||
Version 2.3 Dec 1998 (dillon)
|
||||
- Major bounds checking additions, see FreeBSD/CVS
|
||||
|
||||
Version 3.1 May, 2000 (eds)
|
||||
- Added hooks to handle PPTP.
|
||||
|
||||
See HISTORY file for additional revisions.
|
||||
|
||||
$FreeBSD$
|
||||
@ -90,12 +93,6 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#ifndef IPPROTO_GRE
|
||||
#define IPPROTO_GRE 47
|
||||
#define IPPROTO_ESP 50
|
||||
#define IPPROTO_AH 51
|
||||
#endif
|
||||
|
||||
#include "alias_local.h"
|
||||
#include "alias.h"
|
||||
|
||||
@ -105,6 +102,7 @@
|
||||
#define IRC_CONTROL_PORT_NUMBER_1 6667
|
||||
#define IRC_CONTROL_PORT_NUMBER_2 6668
|
||||
#define CUSEEME_PORT_NUMBER 7648
|
||||
#define PPTP_CONTROL_PORT_NUMBER 1723
|
||||
|
||||
|
||||
|
||||
@ -181,6 +179,7 @@ TcpMonitorOut(struct ip *pip, struct alias_link *link)
|
||||
ProtoAliasIn(), ProtoAliasOut()
|
||||
UdpAliasIn(), UdpAliasOut()
|
||||
TcpAliasIn(), TcpAliasOut()
|
||||
GreAliasIn()
|
||||
|
||||
These routines handle protocol specific details of packet aliasing.
|
||||
One may observe a certain amount of repetitive arithmetic in these
|
||||
@ -234,6 +233,8 @@ static int UdpAliasIn (struct ip *);
|
||||
static int TcpAliasOut(struct ip *, int);
|
||||
static int TcpAliasIn (struct ip *);
|
||||
|
||||
static int GreAliasIn(struct ip *);
|
||||
|
||||
|
||||
static int
|
||||
IcmpAliasIn1(struct ip *pip)
|
||||
@ -725,6 +726,39 @@ ProtoAliasOut(struct ip *pip)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
GreAliasIn(struct ip *pip)
|
||||
{
|
||||
u_short call_id;
|
||||
struct alias_link *link;
|
||||
|
||||
/* Return if proxy-only mode is enabled. */
|
||||
if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
|
||||
return (PKT_ALIAS_OK);
|
||||
|
||||
if (PptpGetCallID(pip, &call_id)) {
|
||||
if ((link = FindPptpIn(pip->ip_src, pip->ip_dst, call_id)) != NULL) {
|
||||
struct in_addr alias_address;
|
||||
struct in_addr original_address;
|
||||
|
||||
alias_address = GetAliasAddress(link);
|
||||
original_address = GetOriginalAddress(link);
|
||||
PptpSetCallID(pip, GetOriginalPort(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);
|
||||
} else
|
||||
return (PKT_ALIAS_IGNORED);
|
||||
} else
|
||||
return ProtoAliasIn(pip);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
UdpAliasIn(struct ip *pip)
|
||||
@ -903,6 +937,11 @@ TcpAliasIn(struct ip *pip)
|
||||
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);
|
||||
@ -1070,9 +1109,12 @@ TcpAliasOut(struct ip *pip, int maxpacketsize)
|
||||
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) == 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 */
|
||||
@ -1301,6 +1343,9 @@ PacketAliasIn(char *ptr, int maxpacketsize)
|
||||
case IPPROTO_TCP:
|
||||
iresult = TcpAliasIn(pip);
|
||||
break;
|
||||
case IPPROTO_GRE:
|
||||
iresult = GreAliasIn(pip);
|
||||
break;
|
||||
default:
|
||||
iresult = ProtoAliasIn(pip);
|
||||
break;
|
||||
|
@ -147,6 +147,7 @@
|
||||
/* Timeouts (in seconds) for different link types */
|
||||
#define ICMP_EXPIRE_TIME 60
|
||||
#define UDP_EXPIRE_TIME 60
|
||||
#define PPTP_EXPIRE_TIME 60
|
||||
#define PROTO_EXPIRE_TIME 60
|
||||
#define FRAGMENT_ID_EXPIRE_TIME 10
|
||||
#define FRAGMENT_PTR_EXPIRE_TIME 30
|
||||
@ -265,6 +266,7 @@ struct alias_link /* Main data structure */
|
||||
#define LINK_FRAGMENT_ID (IPPROTO_MAX + 1)
|
||||
#define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2)
|
||||
#define LINK_ADDR (IPPROTO_MAX + 3)
|
||||
#define LINK_PPTP (IPPROTO_MAX + 4)
|
||||
|
||||
int flags; /* indicates special characteristics */
|
||||
|
||||
@ -329,6 +331,7 @@ linkTableIn[LINK_TABLE_IN_SIZE]; /* into input and output lookup */
|
||||
static int icmpLinkCount; /* Link statistics */
|
||||
static int udpLinkCount;
|
||||
static int tcpLinkCount;
|
||||
static int pptpLinkCount;
|
||||
static int protoLinkCount;
|
||||
static int fragmentIdLinkCount;
|
||||
static int fragmentPtrLinkCount;
|
||||
@ -455,10 +458,11 @@ ShowAliasStats(void)
|
||||
|
||||
if (monitorFile)
|
||||
{
|
||||
fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, proto=%d, frag_id=%d frag_ptr=%d",
|
||||
fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, pptp=%d, proto=%d, frag_id=%d frag_ptr=%d",
|
||||
icmpLinkCount,
|
||||
udpLinkCount,
|
||||
tcpLinkCount,
|
||||
pptpLinkCount,
|
||||
protoLinkCount,
|
||||
fragmentIdLinkCount,
|
||||
fragmentPtrLinkCount);
|
||||
@ -466,6 +470,7 @@ ShowAliasStats(void)
|
||||
fprintf(monitorFile, " / tot=%d (sock=%d)\n",
|
||||
icmpLinkCount + udpLinkCount
|
||||
+ tcpLinkCount
|
||||
+ pptpLinkCount
|
||||
+ protoLinkCount
|
||||
+ fragmentIdLinkCount
|
||||
+ fragmentPtrLinkCount,
|
||||
@ -550,7 +555,7 @@ GetNewPort(struct alias_link *link, int alias_port_param)
|
||||
the port number. GetNewPort() will return this number
|
||||
without check that it is in use.
|
||||
|
||||
When this parameter is -1, it indicates to get a randomly
|
||||
When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
|
||||
selected port number.
|
||||
*/
|
||||
|
||||
@ -618,7 +623,9 @@ GetNewPort(struct alias_link *link, int alias_port_param)
|
||||
if (go_ahead)
|
||||
{
|
||||
if ((packetAliasMode & PKT_ALIAS_USE_SOCKETS)
|
||||
&& (link->flags & LINK_PARTIALLY_SPECIFIED))
|
||||
&& (link->flags & LINK_PARTIALLY_SPECIFIED)
|
||||
&& ((link->link_type == LINK_TCP) ||
|
||||
(link->link_type == LINK_UDP)))
|
||||
{
|
||||
if (GetSocket(port_net, &link->sockfd, link->link_type))
|
||||
{
|
||||
@ -838,6 +845,9 @@ DeleteLink(struct alias_link *link)
|
||||
if (link->data.tcp != NULL)
|
||||
free(link->data.tcp);
|
||||
break;
|
||||
case LINK_PPTP:
|
||||
pptpLinkCount--;
|
||||
break;
|
||||
case LINK_FRAGMENT_ID:
|
||||
fragmentIdLinkCount--;
|
||||
break;
|
||||
@ -906,6 +916,9 @@ AddLink(struct in_addr src_addr,
|
||||
case LINK_TCP:
|
||||
link->expire_time = TCP_EXPIRE_INITIAL;
|
||||
break;
|
||||
case LINK_PPTP:
|
||||
link->expire_time = PPTP_EXPIRE_TIME;
|
||||
break;
|
||||
case LINK_FRAGMENT_ID:
|
||||
link->expire_time = FRAGMENT_ID_EXPIRE_TIME;
|
||||
break;
|
||||
@ -994,6 +1007,9 @@ AddLink(struct in_addr src_addr,
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case LINK_PPTP:
|
||||
pptpLinkCount++;
|
||||
break;
|
||||
case LINK_FRAGMENT_ID:
|
||||
fragmentIdLinkCount++;
|
||||
break;
|
||||
@ -1307,6 +1323,7 @@ FindLinkIn(struct in_addr dst_addr,
|
||||
AddFragmentPtrLink(), FindFragmentPtr()
|
||||
FindProtoIn(), FindProtoOut()
|
||||
FindUdpTcpIn(), FindUdpTcpOut()
|
||||
FindPptpIn(), FindPptpOut()
|
||||
FindOriginalAddress(), FindAliasAddress()
|
||||
|
||||
(prototypes in alias_local.h)
|
||||
@ -1533,6 +1550,56 @@ FindUdpTcpOut(struct in_addr src_addr,
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
FindPptpIn(struct in_addr dst_addr,
|
||||
struct in_addr alias_addr,
|
||||
u_short call_id)
|
||||
{
|
||||
struct alias_link *link;
|
||||
|
||||
link = FindLinkIn(dst_addr, alias_addr,
|
||||
NO_DEST_PORT, call_id,
|
||||
LINK_PPTP, 1);
|
||||
|
||||
if (link == NULL && !(packetAliasMode & PKT_ALIAS_DENY_INCOMING))
|
||||
{
|
||||
struct in_addr target_addr;
|
||||
|
||||
target_addr = FindOriginalAddress(alias_addr);
|
||||
link = AddLink(target_addr, dst_addr, alias_addr,
|
||||
call_id, NO_DEST_PORT, call_id,
|
||||
LINK_PPTP);
|
||||
}
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
FindPptpOut(struct in_addr src_addr,
|
||||
struct in_addr dst_addr,
|
||||
u_short call_id)
|
||||
{
|
||||
struct alias_link *link;
|
||||
|
||||
link = FindLinkOut(src_addr, dst_addr,
|
||||
call_id, NO_DEST_PORT,
|
||||
LINK_PPTP, 1);
|
||||
|
||||
if (link == NULL)
|
||||
{
|
||||
struct in_addr alias_addr;
|
||||
|
||||
alias_addr = FindAliasAddress(src_addr);
|
||||
link = AddLink(src_addr, dst_addr, alias_addr,
|
||||
call_id, NO_DEST_PORT, GET_ALIAS_PORT,
|
||||
LINK_PPTP);
|
||||
}
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct in_addr alias_addr)
|
||||
{
|
||||
@ -2308,6 +2375,7 @@ PacketAliasInit(void)
|
||||
icmpLinkCount = 0;
|
||||
udpLinkCount = 0;
|
||||
tcpLinkCount = 0;
|
||||
pptpLinkCount = 0;
|
||||
protoLinkCount = 0;
|
||||
fragmentIdLinkCount = 0;
|
||||
fragmentPtrLinkCount = 0;
|
||||
|
@ -107,6 +107,12 @@ FindUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
struct alias_link *
|
||||
FindUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
|
||||
struct alias_link *
|
||||
FindPptpIn(struct in_addr, struct in_addr, u_short);
|
||||
|
||||
struct alias_link *
|
||||
FindPptpOut(struct in_addr, struct in_addr, u_short);
|
||||
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct in_addr);
|
||||
|
||||
@ -159,6 +165,12 @@ void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
|
||||
/* IRC routines */
|
||||
void AliasHandleIrcOut(struct ip *, struct alias_link *, int);
|
||||
|
||||
/* PPTP routines */
|
||||
int PptpGetCallID(struct ip *, u_short *);
|
||||
void PptpSetCallID(struct ip *, u_short);
|
||||
void AliasHandlePptpOut(struct ip *, struct alias_link *);
|
||||
void AliasHandlePptpIn(struct ip *, struct alias_link *);
|
||||
|
||||
/* 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 *);
|
||||
|
279
sys/netinet/libalias/alias_pptp.c
Normal file
279
sys/netinet/libalias/alias_pptp.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* alias_pptp.c
|
||||
*
|
||||
* Copyright (c) 2000 Whistle Communications, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Subject to the following obligations and disclaimer of warranty, use and
|
||||
* redistribution of this software, in source or object code forms, with or
|
||||
* without modifications are expressly permitted by Whistle Communications;
|
||||
* provided, however, that:
|
||||
* 1. Any and all reproductions of the source or object code must include the
|
||||
* copyright notice above and the following disclaimer of warranties; and
|
||||
* 2. No rights are granted, in any manner or form, to use Whistle
|
||||
* Communications, Inc. trademarks, including the mark "WHISTLE
|
||||
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
|
||||
* such appears in the above copyright notice or in the software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
|
||||
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
|
||||
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||||
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
|
||||
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
|
||||
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
|
||||
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
|
||||
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
|
||||
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Erik Salander <erik@whistle.com>
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
Alias_pptp.c performs special processing for PPTP sessions under TCP.
|
||||
Specifically, watch PPTP control messages and alias the Call ID or the
|
||||
Peer's Call ID in the appropriate messages. Note, PPTP requires
|
||||
"de-aliasing" of incoming packets, this is different than any other
|
||||
TCP applications that are currently (ie. FTP, IRC and RTSP) aliased.
|
||||
|
||||
For Call IDs encountered for the first time, a GRE alias link is created.
|
||||
The GRE alias link uses the Call ID in place of the original port number.
|
||||
An alias Call ID is created.
|
||||
|
||||
For this routine to work, the PPTP control messages must fit entirely
|
||||
into a single TCP packet. This is typically the case, but is not
|
||||
required by the spec.
|
||||
|
||||
Unlike some of the other TCP applications that are aliased (ie. FTP,
|
||||
IRC and RTSP), the PPTP control messages that need to be aliased are
|
||||
guaranteed to remain the same length. The aliased Call ID is a fixed
|
||||
length field.
|
||||
|
||||
Reference: RFC 2637
|
||||
|
||||
Initial version: May, 2000 (eds)
|
||||
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
/*
|
||||
* PPTP definitions
|
||||
*/
|
||||
|
||||
struct grehdr /* Enhanced GRE header. */
|
||||
{
|
||||
u_char gh_recursion:3, /* Recursion control. */
|
||||
gh_ssr_flag:1, /* Strict source route present. */
|
||||
gh_seq_no_flag:1, /* Sequence number present. */
|
||||
gh_key_flag:1, /* Key present. */
|
||||
gh_rt_flag:1, /* Routing present. */
|
||||
gh_cksum_flag:1; /* Checksum present. */
|
||||
u_char gh_version:3, /* GRE version. */
|
||||
gh_flags:4, /* Flags. */
|
||||
gh_ack_no_flag:1; /* Acknowledgment sequence number present. */
|
||||
u_short gh_protocol; /* Protocol type. */
|
||||
u_short gh_length; /* Payload length. */
|
||||
u_short gh_call_id; /* Call ID. */
|
||||
u_int32_t gh_seq_no; /* Sequence number (optional). */
|
||||
u_int32_t gh_ack_no; /* Acknowledgment number (optional). */
|
||||
};
|
||||
|
||||
/* The PPTP protocol ID used in the GRE 'proto' field. */
|
||||
#define PPTP_GRE_PROTO 0x880b
|
||||
|
||||
/* Bits that must be set a certain way in all PPTP/GRE packets. */
|
||||
#define PPTP_INIT_VALUE ((0x2001 << 16) | PPTP_GRE_PROTO)
|
||||
#define PPTP_INIT_MASK 0xef7fffff
|
||||
|
||||
#define PPTP_MAGIC 0x1a2b3c4d
|
||||
#define PPTP_CTRL_MSG_TYPE 1
|
||||
|
||||
enum {
|
||||
PPTP_StartCtrlConnRequest = 1,
|
||||
PPTP_StartCtrlConnReply = 2,
|
||||
PPTP_StopCtrlConnRequest = 3,
|
||||
PPTP_StopCtrlConnReply = 4,
|
||||
PPTP_EchoRequest = 5,
|
||||
PPTP_statoReply = 6,
|
||||
PPTP_OutCallRequest = 7,
|
||||
PPTP_OutCallReply = 8,
|
||||
PPTP_InCallRequest = 9,
|
||||
PPTP_InCallReply = 10,
|
||||
PPTP_InCallConn = 11,
|
||||
PPTP_CallClearRequest = 12,
|
||||
PPTP_CallDiscNotify = 13,
|
||||
PPTP_WanErrorNotify = 14,
|
||||
PPTP_SetLinkInfo = 15,
|
||||
};
|
||||
|
||||
/* Message structures */
|
||||
struct pptpMsgHead {
|
||||
u_int16_t length; /* total length */
|
||||
u_int16_t msgType; /* PPTP message type */
|
||||
u_int32_t magic; /* magic cookie */
|
||||
u_int16_t type; /* control message type */
|
||||
u_int16_t resv0; /* reserved */
|
||||
};
|
||||
typedef struct pptpMsgHead *PptpMsgHead;
|
||||
|
||||
struct pptpCallIds {
|
||||
u_int16_t cid1; /* Call ID field #1 */
|
||||
u_int16_t cid2; /* Call ID field #2 */
|
||||
};
|
||||
typedef struct pptpCallIds *PptpCallId;
|
||||
|
||||
static PptpCallId AliasVerifyPptp(struct ip *, u_int16_t *);
|
||||
|
||||
int
|
||||
PptpGetCallID(struct ip *pip,
|
||||
u_short *call_id)
|
||||
{
|
||||
struct grehdr *gr;
|
||||
|
||||
gr = (struct grehdr *)((char *)pip + (pip->ip_hl << 2));
|
||||
|
||||
/* Check GRE header bits. */
|
||||
if ((ntohl(*((u_int32_t *)gr)) & PPTP_INIT_MASK) == PPTP_INIT_VALUE) {
|
||||
*call_id = gr->gh_call_id;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
};
|
||||
|
||||
void PptpSetCallID(struct ip *pip, u_short call_id)
|
||||
{
|
||||
struct grehdr *gr;
|
||||
|
||||
gr = (struct grehdr *)((char *)pip + (pip->ip_hl << 2));
|
||||
gr->gh_call_id = call_id;
|
||||
};
|
||||
|
||||
void
|
||||
AliasHandlePptpOut(struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *link) /* The PPTP control link */
|
||||
{
|
||||
struct alias_link *gre_link;
|
||||
PptpCallId cptr;
|
||||
u_int16_t ctl_type; /* control message type */
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Verify valid PPTP control message */
|
||||
if ((cptr = AliasVerifyPptp(pip, &ctl_type)) == NULL)
|
||||
return;
|
||||
|
||||
/* Modify certain PPTP messages */
|
||||
if ((ctl_type >= PPTP_OutCallRequest) &&
|
||||
(ctl_type <= PPTP_CallDiscNotify)) {
|
||||
|
||||
/* Establish GRE link for address and Call ID found in PPTP Control Msg */
|
||||
gre_link = FindPptpOut(GetOriginalAddress(link), GetDestAddress(link),
|
||||
cptr->cid1);
|
||||
|
||||
if (gre_link != NULL) {
|
||||
/* alias the Call Id */
|
||||
cptr->cid1 = GetAliasPort(gre_link);
|
||||
|
||||
/* Compute TCP checksum for revised packet */
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AliasHandlePptpIn(struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *link) /* The PPTP control link */
|
||||
{
|
||||
struct alias_link *gre_link;
|
||||
PptpCallId cptr;
|
||||
u_int16_t *pcall_id;
|
||||
u_int16_t ctl_type; /* control message type */
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Verify valid PPTP control message */
|
||||
if ((cptr = AliasVerifyPptp(pip, &ctl_type)) == NULL)
|
||||
return;
|
||||
|
||||
/* Modify certain PPTP messages */
|
||||
switch (ctl_type)
|
||||
{
|
||||
case PPTP_InCallConn:
|
||||
case PPTP_WanErrorNotify:
|
||||
case PPTP_SetLinkInfo:
|
||||
pcall_id = &cptr->cid1;
|
||||
break;
|
||||
case PPTP_OutCallReply:
|
||||
case PPTP_InCallReply:
|
||||
pcall_id = &cptr->cid2;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find GRE link for address and Call ID found in PPTP Control Msg */
|
||||
gre_link = FindPptpIn(GetDestAddress(link), GetAliasAddress(link),
|
||||
*pcall_id);
|
||||
|
||||
if (gre_link != NULL) {
|
||||
/* alias the Call Id */
|
||||
*pcall_id = GetOriginalPort(gre_link);
|
||||
|
||||
/* Compute TCP checksum for modified packet */
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
}
|
||||
}
|
||||
|
||||
PptpCallId
|
||||
AliasVerifyPptp(struct ip *pip, u_int16_t *ptype) /* IP packet to examine/patch */
|
||||
{
|
||||
int hlen, tlen, dlen;
|
||||
PptpMsgHead hptr;
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Calculate some lengths */
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
tlen = ntohs(pip->ip_len);
|
||||
dlen = tlen - hlen;
|
||||
|
||||
/* Verify data length */
|
||||
if (dlen < (sizeof(struct pptpMsgHead) + sizeof(struct pptpCallIds)))
|
||||
return(NULL);
|
||||
|
||||
/* Move up to PPTP message header */
|
||||
hptr = (PptpMsgHead)(((char *) pip) + hlen);
|
||||
|
||||
/* Return the control message type */
|
||||
*ptype = ntohs(hptr->type);
|
||||
|
||||
/* Verify PPTP Control Message */
|
||||
if ((ntohs(hptr->msgType) != PPTP_CTRL_MSG_TYPE) ||
|
||||
(ntohl(hptr->magic) != PPTP_MAGIC))
|
||||
return(NULL);
|
||||
else
|
||||
return((PptpCallId)(((char *)hptr) + sizeof(struct pptpMsgHead)));
|
||||
}
|
@ -835,6 +835,8 @@ versions 1.0 - 1.8, 2.0 - 2.4.
|
||||
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.
|
||||
.An Erik Salander Aq erik@whistle.com
|
||||
added support for PPTP.
|
||||
.Sh ACKNOWLEDGMENTS
|
||||
Listed below, in approximate chronological order, are individuals who
|
||||
have provided valuable comments and/or debugging assistance.
|
||||
|
Loading…
Reference in New Issue
Block a user