aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuslan Ermilov <ru@FreeBSD.org>2000-06-20 11:41:48 +0000
committerRuslan Ermilov <ru@FreeBSD.org>2000-06-20 11:41:48 +0000
commit55a39fc5a23b1b6cb9d32d9ab9d40de6ad76f7b4 (patch)
tree725e7244ed55e7db4d94b0461ff95070aff947a2
parent953ae31a00008703095d69f15e15175394e838a9 (diff)
downloadsrc-55a39fc5a23b1b6cb9d32d9ab9d40de6ad76f7b4.tar.gz
src-55a39fc5a23b1b6cb9d32d9ab9d40de6ad76f7b4.zip
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>
Notes
Notes: svn path=/head/; revision=61861
-rw-r--r--lib/libalias/HISTORY5
-rw-r--r--lib/libalias/Makefile2
-rw-r--r--lib/libalias/alias.c59
-rw-r--r--lib/libalias/alias_db.c74
-rw-r--r--lib/libalias/alias_local.h12
-rw-r--r--lib/libalias/alias_pptp.c279
-rw-r--r--lib/libalias/libalias.32
-rw-r--r--sys/netinet/libalias/HISTORY5
-rw-r--r--sys/netinet/libalias/Makefile2
-rw-r--r--sys/netinet/libalias/alias.c59
-rw-r--r--sys/netinet/libalias/alias_db.c74
-rw-r--r--sys/netinet/libalias/alias_local.h12
-rw-r--r--sys/netinet/libalias/alias_pptp.c279
-rw-r--r--sys/netinet/libalias/libalias.32
14 files changed, 844 insertions, 22 deletions
diff --git a/lib/libalias/HISTORY b/lib/libalias/HISTORY
index f26299c1573a..8760d92187a1 100644
--- a/lib/libalias/HISTORY
+++ b/lib/libalias/HISTORY
@@ -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.
diff --git a/lib/libalias/Makefile b/lib/libalias/Makefile
index 05411f574d44..32080142ea42 100644
--- a/lib/libalias/Makefile
+++ b/lib/libalias/Makefile
@@ -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
diff --git a/lib/libalias/alias.c b/lib/libalias/alias.c
index eaaedac5db56..e4770fe52681 100644
--- a/lib/libalias/alias.c
+++ b/lib/libalias/alias.c
@@ -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;
diff --git a/lib/libalias/alias_db.c b/lib/libalias/alias_db.c
index 211a7c23781a..408fcdd146f3 100644
--- a/lib/libalias/alias_db.c
+++ b/lib/libalias/alias_db.c
@@ -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;
diff --git a/lib/libalias/alias_local.h b/lib/libalias/alias_local.h
index 783f6b27bc93..439c9ea6a12e 100644
--- a/lib/libalias/alias_local.h
+++ b/lib/libalias/alias_local.h
@@ -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 *);
diff --git a/lib/libalias/alias_pptp.c b/lib/libalias/alias_pptp.c
new file mode 100644
index 000000000000..822cfa61ddff
--- /dev/null
+++ b/lib/libalias/alias_pptp.c
@@ -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)));
+}
diff --git a/lib/libalias/libalias.3 b/lib/libalias/libalias.3
index 3b6998315e7d..53c0d6b9e3fe 100644
--- a/lib/libalias/libalias.3
+++ b/lib/libalias/libalias.3
@@ -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.
diff --git a/sys/netinet/libalias/HISTORY b/sys/netinet/libalias/HISTORY
index f26299c1573a..8760d92187a1 100644
--- a/sys/netinet/libalias/HISTORY
+++ b/sys/netinet/libalias/HISTORY
@@ -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.
diff --git a/sys/netinet/libalias/Makefile b/sys/netinet/libalias/Makefile
index 05411f574d44..32080142ea42 100644
--- a/sys/netinet/libalias/Makefile
+++ b/sys/netinet/libalias/Makefile
@@ -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
diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c
index eaaedac5db56..e4770fe52681 100644
--- a/sys/netinet/libalias/alias.c
+++ b/sys/netinet/libalias/alias.c
@@ -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;
diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c
index 211a7c23781a..408fcdd146f3 100644
--- a/sys/netinet/libalias/alias_db.c
+++ b/sys/netinet/libalias/alias_db.c
@@ -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;
diff --git a/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h
index 783f6b27bc93..439c9ea6a12e 100644
--- a/sys/netinet/libalias/alias_local.h
+++ b/sys/netinet/libalias/alias_local.h
@@ -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 *);
diff --git a/sys/netinet/libalias/alias_pptp.c b/sys/netinet/libalias/alias_pptp.c
new file mode 100644
index 000000000000..822cfa61ddff
--- /dev/null
+++ b/sys/netinet/libalias/alias_pptp.c
@@ -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)));
+}
diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3
index 3b6998315e7d..53c0d6b9e3fe 100644
--- a/sys/netinet/libalias/libalias.3
+++ b/sys/netinet/libalias/libalias.3
@@ -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.