Add address translation support for RTSP/RTP used by RealPlayer and
Quicktime streaming media applications. Add a BUGS section to the man page. Submitted by: Erik Salander <erik@whistle.com>
This commit is contained in:
parent
a6c8be39c9
commit
642e43b39b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=63899
@ -139,3 +139,7 @@ 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.
|
||||
|
||||
Version 3.2: July, 2000 (Erik Salander, erik@whistle.com and
|
||||
Junichi Satoh, junichi@junichi.org)
|
||||
- Added support for streaming media (RTSP and PNA) aliasing.
|
||||
|
@ -5,7 +5,8 @@ SHLIB_MAJOR= 4
|
||||
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_pptp.c alias_proxy.c alias_util.c
|
||||
alias_nbt.c alias_pptp.c alias_proxy.c alias_smedia.c \
|
||||
alias_util.c
|
||||
INCS= alias.h
|
||||
MAN3= libalias.3
|
||||
|
||||
|
@ -76,9 +76,13 @@
|
||||
Version 2.3 Dec 1998 (dillon)
|
||||
- Major bounds checking additions, see FreeBSD/CVS
|
||||
|
||||
Version 3.1 May, 2000 (eds)
|
||||
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.
|
||||
|
||||
See HISTORY file for additional revisions.
|
||||
|
||||
$FreeBSD$
|
||||
@ -102,6 +106,8 @@
|
||||
#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
|
||||
|
||||
|
||||
@ -1112,6 +1118,11 @@ TcpAliasOut(struct ip *pip, int maxpacketsize)
|
||||
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);
|
||||
@ -1236,6 +1247,7 @@ FragmentOut(struct ip *pip)
|
||||
PacketAliasFragmentIn()
|
||||
PacketAliasIn()
|
||||
PacketAliasOut()
|
||||
PacketUnaliasOut()
|
||||
|
||||
(prototypes in alias.h)
|
||||
*/
|
||||
@ -1465,3 +1477,124 @@ PacketAliasOut(char *ptr, /* valid IP packet */
|
||||
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 = QueryUdpTcpIn(pip->ip_dst, pip->ip_src,
|
||||
ud->uh_dport, ud->uh_sport,
|
||||
IPPROTO_UDP);
|
||||
else if (pip->ip_p == IPPROTO_TCP)
|
||||
link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src,
|
||||
tc->th_dport, tc->th_sport,
|
||||
IPPROTO_TCP);
|
||||
else if (pip->ip_p == IPPROTO_ICMP)
|
||||
link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id);
|
||||
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);
|
||||
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ struct alias_link;
|
||||
extern int
|
||||
PacketAliasOut(char *, int maxpacketsize);
|
||||
|
||||
extern int
|
||||
PacketUnaliasOut(char *, int maxpacketsize);
|
||||
|
||||
/* Port and Address Redirection */
|
||||
extern struct alias_link *
|
||||
PacketAliasRedirectPort(struct in_addr, u_short,
|
||||
|
@ -103,6 +103,16 @@
|
||||
version of PacketAliasPermanentLink(). The second function
|
||||
implements static network address translation.
|
||||
|
||||
Version 3.2: July, 2000 (salander and satoh)
|
||||
Added FindNewPortGroup to get contiguous range of port values.
|
||||
|
||||
Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
|
||||
link but not actually add one.
|
||||
|
||||
Added FindRtspOut, which is closely derived from FindUdpTcpOut,
|
||||
except that the alias port (from FindNewPortGroup) is provided
|
||||
as input.
|
||||
|
||||
See HISTORY file for additional revisions.
|
||||
|
||||
$FreeBSD$
|
||||
@ -500,6 +510,9 @@ Link creation and deletion:
|
||||
Link search:
|
||||
FindLinkOut() - find link for outgoing packets
|
||||
FindLinkIn() - find link for incoming packets
|
||||
|
||||
Port search:
|
||||
FindNewPortGroup() - find an available group of ports
|
||||
*/
|
||||
|
||||
/* Local prototypes */
|
||||
@ -531,11 +544,14 @@ FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int);
|
||||
|
||||
#define ALIAS_PORT_BASE 0x08000
|
||||
#define ALIAS_PORT_MASK 0x07fff
|
||||
#define ALIAS_PORT_MASK_EVEN 0x07ffe
|
||||
#define GET_NEW_PORT_MAX_ATTEMPTS 20
|
||||
|
||||
#define GET_ALIAS_PORT -1
|
||||
#define GET_ALIAS_ID GET_ALIAS_PORT
|
||||
|
||||
#define FIND_EVEN_ALIAS_BASE 1
|
||||
|
||||
/* GetNewPort() allocates port numbers. Note that if a port number
|
||||
is already in use, that does not mean that it cannot be used by
|
||||
another link concurrently. This is because GetNewPort() looks for
|
||||
@ -704,6 +720,102 @@ GetSocket(u_short port_net, int *sockfd, int link_type)
|
||||
}
|
||||
|
||||
|
||||
/* FindNewPortGroup() returns a base port number for an available
|
||||
range of contiguous port numbers. Note that if a port number
|
||||
is already in use, that does not mean that it cannot be used by
|
||||
another link concurrently. This is because FindNewPortGroup()
|
||||
looks for unused triplets: (dest addr, dest port, alias port). */
|
||||
|
||||
int
|
||||
FindNewPortGroup(struct in_addr dst_addr,
|
||||
struct in_addr alias_addr,
|
||||
u_short src_port,
|
||||
u_short dst_port,
|
||||
u_short port_count,
|
||||
u_char proto,
|
||||
u_char align)
|
||||
{
|
||||
int i, j;
|
||||
int max_trials;
|
||||
u_short port_sys;
|
||||
int link_type;
|
||||
|
||||
/*
|
||||
* Get link_type from protocol
|
||||
*/
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_UDP:
|
||||
link_type = LINK_UDP;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
link_type = LINK_TCP;
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The aliasing port is automatically selected
|
||||
* by one of two methods below:
|
||||
*/
|
||||
max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
|
||||
|
||||
if (packetAliasMode & PKT_ALIAS_SAME_PORTS) {
|
||||
/*
|
||||
* When the ALIAS_SAME_PORTS option is
|
||||
* chosen, the first try will be the
|
||||
* actual source port. If this is already
|
||||
* in use, the remainder of the trials
|
||||
* will be random.
|
||||
*/
|
||||
port_sys = ntohs(src_port);
|
||||
|
||||
} else {
|
||||
|
||||
/* First trial and all subsequent are random. */
|
||||
if (align == FIND_EVEN_ALIAS_BASE)
|
||||
port_sys = random() & ALIAS_PORT_MASK_EVEN;
|
||||
else
|
||||
port_sys = random() & ALIAS_PORT_MASK;
|
||||
|
||||
port_sys += ALIAS_PORT_BASE;
|
||||
}
|
||||
|
||||
/* Port number search */
|
||||
for (i = 0; i < max_trials; i++) {
|
||||
|
||||
struct alias_link *search_result;
|
||||
|
||||
for (j = 0; j < port_count; j++)
|
||||
if (0 != (search_result = FindLinkIn(dst_addr, alias_addr,
|
||||
dst_port, htons(port_sys + j),
|
||||
link_type, 0)))
|
||||
break;
|
||||
|
||||
/* Found a good range, return base */
|
||||
if (j == port_count)
|
||||
return (htons(port_sys));
|
||||
|
||||
/* Find a new base to try */
|
||||
if (align == FIND_EVEN_ALIAS_BASE)
|
||||
port_sys = random() & ALIAS_PORT_MASK_EVEN;
|
||||
else
|
||||
port_sys = random() & ALIAS_PORT_MASK;
|
||||
|
||||
port_sys += ALIAS_PORT_BASE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
|
||||
fprintf(stderr, "could not find free port(s)\n");
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
CleanupAliasData(void)
|
||||
{
|
||||
@ -1600,6 +1712,107 @@ FindPptpOut(struct in_addr src_addr,
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
QueryUdpTcpIn(struct in_addr dst_addr,
|
||||
struct in_addr alias_addr,
|
||||
u_short dst_port,
|
||||
u_short alias_port,
|
||||
u_char proto)
|
||||
{
|
||||
int link_type;
|
||||
struct alias_link *link;
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_UDP:
|
||||
link_type = LINK_UDP;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
link_type = LINK_TCP;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
link = FindLinkIn(dst_addr, alias_addr,
|
||||
dst_port, alias_port,
|
||||
link_type, 0);
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
QueryUdpTcpOut(struct in_addr src_addr,
|
||||
struct in_addr dst_addr,
|
||||
u_short src_port,
|
||||
u_short dst_port,
|
||||
u_char proto)
|
||||
{
|
||||
int link_type;
|
||||
struct alias_link *link;
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_UDP:
|
||||
link_type = LINK_UDP;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
link_type = LINK_TCP;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
link = FindLinkOut(src_addr, dst_addr,
|
||||
src_port, dst_port,
|
||||
link_type, 0);
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
FindRtspOut(struct in_addr src_addr,
|
||||
struct in_addr dst_addr,
|
||||
u_short src_port,
|
||||
u_short alias_port,
|
||||
u_char proto)
|
||||
{
|
||||
int link_type;
|
||||
struct alias_link *link;
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_UDP:
|
||||
link_type = LINK_UDP;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
link_type = LINK_TCP;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
link = FindLinkOut(src_addr, dst_addr, src_port, 0, link_type, 1);
|
||||
|
||||
if (link == NULL)
|
||||
{
|
||||
struct in_addr alias_addr;
|
||||
|
||||
alias_addr = FindAliasAddress(src_addr);
|
||||
link = AddLink(src_addr, dst_addr, alias_addr,
|
||||
src_port, 0, alias_port,
|
||||
link_type);
|
||||
}
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct in_addr alias_addr)
|
||||
{
|
||||
|
@ -113,6 +113,15 @@ FindPptpIn(struct in_addr, struct in_addr, u_short);
|
||||
struct alias_link *
|
||||
FindPptpOut(struct in_addr, struct in_addr, u_short);
|
||||
|
||||
struct alias_link *
|
||||
QueryUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
|
||||
struct alias_link *
|
||||
QueryUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
|
||||
struct alias_link *
|
||||
FindRtspOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct in_addr);
|
||||
|
||||
@ -120,6 +129,8 @@ struct in_addr
|
||||
FindAliasAddress(struct in_addr);
|
||||
|
||||
/* External data access/modification */
|
||||
int FindNewPortGroup(struct in_addr, struct in_addr,
|
||||
u_short, u_short, u_short, u_char, u_char);
|
||||
void GetFragmentAddr(struct alias_link *, struct in_addr *);
|
||||
void SetFragmentAddr(struct alias_link *, struct in_addr);
|
||||
void GetFragmentPtr(struct alias_link *, char **);
|
||||
@ -165,6 +176,9 @@ void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
|
||||
/* IRC routines */
|
||||
void AliasHandleIrcOut(struct ip *, struct alias_link *, int);
|
||||
|
||||
/* RTSP routines */
|
||||
void AliasHandleRtspOut(struct ip *, struct alias_link *, int);
|
||||
|
||||
/* PPTP routines */
|
||||
int PptpGetCallID(struct ip *, u_short *);
|
||||
void PptpSetCallID(struct ip *, u_short);
|
||||
|
427
lib/libalias/alias_smedia.c
Normal file
427
lib/libalias/alias_smedia.c
Normal file
@ -0,0 +1,427 @@
|
||||
/*
|
||||
* alias_smedia.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.
|
||||
*
|
||||
* Copyright (c) 2000 Junichi SATOH <junichi@astec.co.jp>
|
||||
* <junichi@junichi.org>
|
||||
* 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.
|
||||
*
|
||||
* Authors: Erik Salander <erik@whistle.com>
|
||||
* Junichi SATOH <junichi@astec.co.jp>
|
||||
* <junichi@junichi.org>
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
Alias_smedia.c is meant to contain the aliasing code for streaming media
|
||||
protocols. It performs special processing for RSTP sessions under TCP.
|
||||
Specifically, when a SETUP request is sent by a client, or a 200 reply
|
||||
is sent by a server, it is intercepted and modified. The address is
|
||||
changed to the gateway machine and an aliasing port is used.
|
||||
|
||||
More specifically, the "client_port" configuration parameter is
|
||||
parsed for SETUP requests. The "server_port" configuration parameter is
|
||||
parsed for 200 replies eminating from a server. This is intended to handle
|
||||
the unicast case.
|
||||
|
||||
RTSP also allows a redirection of a stream to another client by using the
|
||||
"destination" configuration parameter. The destination config parm would
|
||||
indicate a different IP address. This function is NOT supported by the
|
||||
RTSP translation code below.
|
||||
|
||||
The RTSP multicast functions without any address translation intervention.
|
||||
|
||||
For this routine to work, the SETUP/200 must fit entirely
|
||||
into a single TCP packet. This is typically the case, but exceptions
|
||||
can easily be envisioned under the actual specifications.
|
||||
|
||||
Probably the most troubling aspect of the approach taken here is
|
||||
that the new SETUP/200 will typically be a different length, and
|
||||
this causes a certain amount of bookkeeping to keep track of the
|
||||
changes of sequence and acknowledgment numbers, since the client
|
||||
machine is totally unaware of the modification to the TCP stream.
|
||||
|
||||
Initial version: May, 2000 (eds)
|
||||
*/
|
||||
|
||||
#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 <netinet/udp.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
#define RTSP_CONTROL_PORT_NUMBER_1 554
|
||||
#define RTSP_CONTROL_PORT_NUMBER_2 7070
|
||||
#define RTSP_PORT_GROUP 2
|
||||
|
||||
#define ISDIGIT(a) (((a) >= '0') && ((a) <= '9'))
|
||||
|
||||
int search_string(char *data, int dlen, char *search_str)
|
||||
{
|
||||
int i, j, k;
|
||||
int search_str_len;
|
||||
|
||||
search_str_len = strlen(search_str);
|
||||
for (i = 0; i < dlen - search_str_len; i++) {
|
||||
for (j = i, k = 0; j < dlen - search_str_len; j++, k++) {
|
||||
if (data[j] != search_str[k] &&
|
||||
data[j] != search_str[k] - ('a' - 'A')) {
|
||||
break;
|
||||
}
|
||||
if (k == search_str_len - 1) {
|
||||
return j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int alias_rtsp_out(struct ip *pip,
|
||||
struct alias_link *link,
|
||||
char *data,
|
||||
char *port_str)
|
||||
{
|
||||
int hlen, tlen, dlen;
|
||||
struct tcphdr *tc;
|
||||
int i, j, pos, state, port_dlen, new_dlen, delta;
|
||||
u_short p[2], new_len;
|
||||
u_short sport, eport, base_port;
|
||||
u_short salias = 0, ealias = 0, base_alias = 0;
|
||||
char *transport_str = "transport:";
|
||||
char newdata[2048], *port_data, *port_newdata, stemp[80];
|
||||
int links_created = 0, pkt_updated = 0;
|
||||
struct alias_link *rtsp_link = NULL;
|
||||
struct in_addr null_addr;
|
||||
|
||||
/* Calculate data length of TCP packet */
|
||||
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;
|
||||
|
||||
/* Find keyword, "Transport: " */
|
||||
pos = search_string(data, dlen, transport_str);
|
||||
if (pos < 0) {
|
||||
return -1;
|
||||
}
|
||||
port_data = data + pos;
|
||||
port_dlen = dlen - pos;
|
||||
|
||||
memcpy(newdata, data, pos);
|
||||
port_newdata = newdata + pos;
|
||||
|
||||
while (port_dlen > strlen(port_str)) {
|
||||
/* Find keyword, appropriate port string */
|
||||
pos = search_string(port_data, port_dlen, port_str);
|
||||
if (pos < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy (port_newdata, port_data, pos + 1);
|
||||
port_newdata += (pos + 1);
|
||||
|
||||
p[0] = p[1] = 0;
|
||||
sport = eport = 0;
|
||||
state = 0;
|
||||
for (i = pos; i < port_dlen; i++) {
|
||||
switch(state) {
|
||||
case 0:
|
||||
if (port_data[i] == '=') {
|
||||
state++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (ISDIGIT(port_data[i])) {
|
||||
p[0] = p[0] * 10 + port_data[i] - '0';
|
||||
} else {
|
||||
if (port_data[i] == ';') {
|
||||
state = 3;
|
||||
}
|
||||
if (port_data[i] == '-') {
|
||||
state++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (ISDIGIT(port_data[i])) {
|
||||
p[1] = p[1] * 10 + port_data[i] - '0';
|
||||
} else {
|
||||
state++;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
base_port = p[0];
|
||||
sport = htons(p[0]);
|
||||
eport = htons(p[1]);
|
||||
|
||||
if (!links_created) {
|
||||
|
||||
links_created = 1;
|
||||
/* Find an even numbered port number base that
|
||||
satisfies the contiguous number of ports we need */
|
||||
null_addr.s_addr = 0;
|
||||
if (0 == (salias = FindNewPortGroup(null_addr,
|
||||
FindAliasAddress(pip->ip_src),
|
||||
sport, 0,
|
||||
RTSP_PORT_GROUP,
|
||||
IPPROTO_UDP, 1))) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/RTSP: Cannot find contiguous RTSP data ports\n");
|
||||
#endif
|
||||
} else {
|
||||
|
||||
base_alias = ntohs(salias);
|
||||
for (j = 0; j < RTSP_PORT_GROUP; j++) {
|
||||
/* Establish link to port found in RTSP packet */
|
||||
rtsp_link = FindRtspOut(GetOriginalAddress(link), null_addr,
|
||||
htons(base_port + j), htons(base_alias + j),
|
||||
IPPROTO_UDP);
|
||||
if (rtsp_link != NULL) {
|
||||
#ifndef NO_FW_PUNCH
|
||||
/* Punch hole in firewall */
|
||||
PunchFWHole(rtsp_link);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/RTSP: Cannot allocate RTSP data ports\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ealias = htons(base_alias + (RTSP_PORT_GROUP - 1));
|
||||
}
|
||||
|
||||
if (salias && rtsp_link) {
|
||||
|
||||
pkt_updated = 1;
|
||||
|
||||
/* Copy into IP packet */
|
||||
sprintf(stemp, "%d", ntohs(salias));
|
||||
memcpy(port_newdata, stemp, strlen(stemp));
|
||||
port_newdata += strlen(stemp);
|
||||
|
||||
if (eport != 0) {
|
||||
*port_newdata = '-';
|
||||
port_newdata++;
|
||||
|
||||
/* Copy into IP packet */
|
||||
sprintf(stemp, "%d", ntohs(ealias));
|
||||
memcpy(port_newdata, stemp, strlen(stemp));
|
||||
port_newdata += strlen(stemp);
|
||||
}
|
||||
|
||||
*port_newdata = ';';
|
||||
port_newdata++;
|
||||
}
|
||||
state++;
|
||||
break;
|
||||
}
|
||||
if (state > 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
port_data += i;
|
||||
port_dlen -= i;
|
||||
}
|
||||
|
||||
if (!pkt_updated)
|
||||
return -1;
|
||||
|
||||
memcpy (port_newdata, port_data, port_dlen);
|
||||
port_newdata += port_dlen;
|
||||
*port_newdata = '\0';
|
||||
|
||||
/* Create new packet */
|
||||
new_dlen = port_newdata - newdata;
|
||||
memcpy (data, newdata, new_dlen);
|
||||
|
||||
SetAckModified(link);
|
||||
delta = GetDeltaSeqOut(pip, link);
|
||||
AddSeq(pip, link, delta + new_dlen - dlen);
|
||||
|
||||
new_len = htons(hlen + new_dlen);
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
&new_len,
|
||||
&pip->ip_len,
|
||||
1);
|
||||
pip->ip_len = new_len;
|
||||
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Support the protocol used by early versions of RealPlayer */
|
||||
|
||||
int alias_pna_out(struct ip *pip,
|
||||
struct alias_link *link,
|
||||
char *data,
|
||||
int dlen)
|
||||
{
|
||||
struct alias_link *pna_links;
|
||||
u_short msg_id, msg_len;
|
||||
char *work;
|
||||
u_short alias_port, port;
|
||||
struct tcphdr *tc;
|
||||
|
||||
work = data;
|
||||
work += 5;
|
||||
while (work + 4 < data + dlen) {
|
||||
memcpy(&msg_id, work, 2);
|
||||
work += 2;
|
||||
memcpy(&msg_len, work, 2);
|
||||
work += 2;
|
||||
if (ntohs(msg_id) == 0) {
|
||||
/* end of options */
|
||||
return 0;
|
||||
}
|
||||
if ((ntohs(msg_id) == 1) || (ntohs(msg_id) == 7)) {
|
||||
memcpy((char*)&port, (char*)work, 2);
|
||||
pna_links = FindUdpTcpOut(pip->ip_src, GetDestAddress(link),
|
||||
port, 0, IPPROTO_UDP);
|
||||
if (pna_links != NULL) {
|
||||
#ifndef NO_FW_PUNCH
|
||||
/* Punch hole in firewall */
|
||||
PunchFWHole(pna_links);
|
||||
#endif
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
alias_port = GetAliasPort(pna_links);
|
||||
memcpy((char*)work, (char*)&alias_port, 2);
|
||||
|
||||
/* Compute TCP checksum for revised packet */
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
}
|
||||
}
|
||||
work += ntohs(msg_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
AliasHandleRtspOut(struct ip *pip, struct alias_link *link, int maxpacketsize)
|
||||
{
|
||||
int hlen, tlen, dlen;
|
||||
struct tcphdr *tc;
|
||||
char *data, *setup = "SETUP", *pna = "PNA", *str200 = "200", *okstr = "OK";
|
||||
char *client_port_str = "client_port", *server_port_str = "server_port";
|
||||
int i, parseOk;
|
||||
|
||||
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;
|
||||
|
||||
data = (char*)pip;
|
||||
data += hlen;
|
||||
|
||||
/* When aliasing a client, check for the SETUP request */
|
||||
if ((ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1) ||
|
||||
(ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2)) {
|
||||
|
||||
if (dlen >= strlen(setup)) {
|
||||
if (memcmp(data, setup, strlen(setup)) == 0) {
|
||||
alias_rtsp_out(pip, link, data, client_port_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dlen >= strlen(pna)) {
|
||||
if (memcmp(data, pna, strlen(pna)) == 0) {
|
||||
alias_pna_out(pip, link, data, dlen);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* When aliasing a server, check for the 200 reply
|
||||
Accomodate varying number of blanks between 200 & OK */
|
||||
|
||||
if (dlen >= strlen(str200)) {
|
||||
|
||||
for (parseOk = 0, i = 0;
|
||||
i <= dlen - strlen(str200);
|
||||
i++) {
|
||||
if (memcmp(&data[i], str200, strlen(str200)) == 0) {
|
||||
parseOk = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parseOk) {
|
||||
|
||||
i += strlen(str200); /* skip string found */
|
||||
while(data[i] == ' ') /* skip blank(s) */
|
||||
i++;
|
||||
|
||||
if ((dlen - i) >= strlen(okstr)) {
|
||||
|
||||
if (memcmp(&data[i], okstr, strlen(okstr)) == 0)
|
||||
alias_rtsp_out(pip, link, data, server_port_str);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -808,6 +808,25 @@ If the checksum is valid,
|
||||
.Fn PacketAliasInternetChecksum
|
||||
will return zero.
|
||||
.Ed
|
||||
.Pp
|
||||
.Ft int
|
||||
.Fn PacketUnaliasOut "char *buffer" "int maxpacketsize"
|
||||
.Bd -ragged -offset indent
|
||||
An outgoing packet, which has already been aliased, has its private address/port
|
||||
information restored by this function.
|
||||
The IP packet is pointed to by
|
||||
.Fa buffer ,
|
||||
and
|
||||
.Fa maxpacketsize
|
||||
is provided for error checking purposes.
|
||||
This function can be used if an already-aliased packet needs to have its
|
||||
original IP header restored for further processing (eg. logging).
|
||||
.Ed
|
||||
.Sh BUGS
|
||||
PPTP aliasing does not work when more than one internal client
|
||||
connects to the same external server at the same time, because
|
||||
PPTP requires a single TCP control connection to be established
|
||||
between any two IP addresses.
|
||||
.Sh AUTHORS
|
||||
.An Charles Mott Aq cmott@scientech.com ,
|
||||
versions 1.0 - 1.8, 2.0 - 2.4.
|
||||
@ -816,7 +835,9 @@ 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.
|
||||
added support for PPTP and RTSP.
|
||||
.An Junichi Satoh Aq junichi@junichi.org
|
||||
added support for RTSP/PNA.
|
||||
.Sh ACKNOWLEDGMENTS
|
||||
Listed below, in approximate chronological order, are individuals who
|
||||
have provided valuable comments and/or debugging assistance.
|
||||
|
@ -139,3 +139,7 @@ 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.
|
||||
|
||||
Version 3.2: July, 2000 (Erik Salander, erik@whistle.com and
|
||||
Junichi Satoh, junichi@junichi.org)
|
||||
- Added support for streaming media (RTSP and PNA) aliasing.
|
||||
|
@ -5,7 +5,8 @@ SHLIB_MAJOR= 4
|
||||
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_pptp.c alias_proxy.c alias_util.c
|
||||
alias_nbt.c alias_pptp.c alias_proxy.c alias_smedia.c \
|
||||
alias_util.c
|
||||
INCS= alias.h
|
||||
MAN3= libalias.3
|
||||
|
||||
|
@ -76,9 +76,13 @@
|
||||
Version 2.3 Dec 1998 (dillon)
|
||||
- Major bounds checking additions, see FreeBSD/CVS
|
||||
|
||||
Version 3.1 May, 2000 (eds)
|
||||
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.
|
||||
|
||||
See HISTORY file for additional revisions.
|
||||
|
||||
$FreeBSD$
|
||||
@ -102,6 +106,8 @@
|
||||
#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
|
||||
|
||||
|
||||
@ -1112,6 +1118,11 @@ TcpAliasOut(struct ip *pip, int maxpacketsize)
|
||||
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);
|
||||
@ -1236,6 +1247,7 @@ FragmentOut(struct ip *pip)
|
||||
PacketAliasFragmentIn()
|
||||
PacketAliasIn()
|
||||
PacketAliasOut()
|
||||
PacketUnaliasOut()
|
||||
|
||||
(prototypes in alias.h)
|
||||
*/
|
||||
@ -1465,3 +1477,124 @@ PacketAliasOut(char *ptr, /* valid IP packet */
|
||||
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 = QueryUdpTcpIn(pip->ip_dst, pip->ip_src,
|
||||
ud->uh_dport, ud->uh_sport,
|
||||
IPPROTO_UDP);
|
||||
else if (pip->ip_p == IPPROTO_TCP)
|
||||
link = QueryUdpTcpIn(pip->ip_dst, pip->ip_src,
|
||||
tc->th_dport, tc->th_sport,
|
||||
IPPROTO_TCP);
|
||||
else if (pip->ip_p == IPPROTO_ICMP)
|
||||
link = FindIcmpIn(pip->ip_dst, pip->ip_src, ic->icmp_id);
|
||||
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);
|
||||
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ struct alias_link;
|
||||
extern int
|
||||
PacketAliasOut(char *, int maxpacketsize);
|
||||
|
||||
extern int
|
||||
PacketUnaliasOut(char *, int maxpacketsize);
|
||||
|
||||
/* Port and Address Redirection */
|
||||
extern struct alias_link *
|
||||
PacketAliasRedirectPort(struct in_addr, u_short,
|
||||
|
@ -103,6 +103,16 @@
|
||||
version of PacketAliasPermanentLink(). The second function
|
||||
implements static network address translation.
|
||||
|
||||
Version 3.2: July, 2000 (salander and satoh)
|
||||
Added FindNewPortGroup to get contiguous range of port values.
|
||||
|
||||
Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
|
||||
link but not actually add one.
|
||||
|
||||
Added FindRtspOut, which is closely derived from FindUdpTcpOut,
|
||||
except that the alias port (from FindNewPortGroup) is provided
|
||||
as input.
|
||||
|
||||
See HISTORY file for additional revisions.
|
||||
|
||||
$FreeBSD$
|
||||
@ -500,6 +510,9 @@ Link creation and deletion:
|
||||
Link search:
|
||||
FindLinkOut() - find link for outgoing packets
|
||||
FindLinkIn() - find link for incoming packets
|
||||
|
||||
Port search:
|
||||
FindNewPortGroup() - find an available group of ports
|
||||
*/
|
||||
|
||||
/* Local prototypes */
|
||||
@ -531,11 +544,14 @@ FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int);
|
||||
|
||||
#define ALIAS_PORT_BASE 0x08000
|
||||
#define ALIAS_PORT_MASK 0x07fff
|
||||
#define ALIAS_PORT_MASK_EVEN 0x07ffe
|
||||
#define GET_NEW_PORT_MAX_ATTEMPTS 20
|
||||
|
||||
#define GET_ALIAS_PORT -1
|
||||
#define GET_ALIAS_ID GET_ALIAS_PORT
|
||||
|
||||
#define FIND_EVEN_ALIAS_BASE 1
|
||||
|
||||
/* GetNewPort() allocates port numbers. Note that if a port number
|
||||
is already in use, that does not mean that it cannot be used by
|
||||
another link concurrently. This is because GetNewPort() looks for
|
||||
@ -704,6 +720,102 @@ GetSocket(u_short port_net, int *sockfd, int link_type)
|
||||
}
|
||||
|
||||
|
||||
/* FindNewPortGroup() returns a base port number for an available
|
||||
range of contiguous port numbers. Note that if a port number
|
||||
is already in use, that does not mean that it cannot be used by
|
||||
another link concurrently. This is because FindNewPortGroup()
|
||||
looks for unused triplets: (dest addr, dest port, alias port). */
|
||||
|
||||
int
|
||||
FindNewPortGroup(struct in_addr dst_addr,
|
||||
struct in_addr alias_addr,
|
||||
u_short src_port,
|
||||
u_short dst_port,
|
||||
u_short port_count,
|
||||
u_char proto,
|
||||
u_char align)
|
||||
{
|
||||
int i, j;
|
||||
int max_trials;
|
||||
u_short port_sys;
|
||||
int link_type;
|
||||
|
||||
/*
|
||||
* Get link_type from protocol
|
||||
*/
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_UDP:
|
||||
link_type = LINK_UDP;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
link_type = LINK_TCP;
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The aliasing port is automatically selected
|
||||
* by one of two methods below:
|
||||
*/
|
||||
max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
|
||||
|
||||
if (packetAliasMode & PKT_ALIAS_SAME_PORTS) {
|
||||
/*
|
||||
* When the ALIAS_SAME_PORTS option is
|
||||
* chosen, the first try will be the
|
||||
* actual source port. If this is already
|
||||
* in use, the remainder of the trials
|
||||
* will be random.
|
||||
*/
|
||||
port_sys = ntohs(src_port);
|
||||
|
||||
} else {
|
||||
|
||||
/* First trial and all subsequent are random. */
|
||||
if (align == FIND_EVEN_ALIAS_BASE)
|
||||
port_sys = random() & ALIAS_PORT_MASK_EVEN;
|
||||
else
|
||||
port_sys = random() & ALIAS_PORT_MASK;
|
||||
|
||||
port_sys += ALIAS_PORT_BASE;
|
||||
}
|
||||
|
||||
/* Port number search */
|
||||
for (i = 0; i < max_trials; i++) {
|
||||
|
||||
struct alias_link *search_result;
|
||||
|
||||
for (j = 0; j < port_count; j++)
|
||||
if (0 != (search_result = FindLinkIn(dst_addr, alias_addr,
|
||||
dst_port, htons(port_sys + j),
|
||||
link_type, 0)))
|
||||
break;
|
||||
|
||||
/* Found a good range, return base */
|
||||
if (j == port_count)
|
||||
return (htons(port_sys));
|
||||
|
||||
/* Find a new base to try */
|
||||
if (align == FIND_EVEN_ALIAS_BASE)
|
||||
port_sys = random() & ALIAS_PORT_MASK_EVEN;
|
||||
else
|
||||
port_sys = random() & ALIAS_PORT_MASK;
|
||||
|
||||
port_sys += ALIAS_PORT_BASE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
|
||||
fprintf(stderr, "could not find free port(s)\n");
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
CleanupAliasData(void)
|
||||
{
|
||||
@ -1600,6 +1712,107 @@ FindPptpOut(struct in_addr src_addr,
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
QueryUdpTcpIn(struct in_addr dst_addr,
|
||||
struct in_addr alias_addr,
|
||||
u_short dst_port,
|
||||
u_short alias_port,
|
||||
u_char proto)
|
||||
{
|
||||
int link_type;
|
||||
struct alias_link *link;
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_UDP:
|
||||
link_type = LINK_UDP;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
link_type = LINK_TCP;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
link = FindLinkIn(dst_addr, alias_addr,
|
||||
dst_port, alias_port,
|
||||
link_type, 0);
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
QueryUdpTcpOut(struct in_addr src_addr,
|
||||
struct in_addr dst_addr,
|
||||
u_short src_port,
|
||||
u_short dst_port,
|
||||
u_char proto)
|
||||
{
|
||||
int link_type;
|
||||
struct alias_link *link;
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_UDP:
|
||||
link_type = LINK_UDP;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
link_type = LINK_TCP;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
link = FindLinkOut(src_addr, dst_addr,
|
||||
src_port, dst_port,
|
||||
link_type, 0);
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct alias_link *
|
||||
FindRtspOut(struct in_addr src_addr,
|
||||
struct in_addr dst_addr,
|
||||
u_short src_port,
|
||||
u_short alias_port,
|
||||
u_char proto)
|
||||
{
|
||||
int link_type;
|
||||
struct alias_link *link;
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_UDP:
|
||||
link_type = LINK_UDP;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
link_type = LINK_TCP;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
link = FindLinkOut(src_addr, dst_addr, src_port, 0, link_type, 1);
|
||||
|
||||
if (link == NULL)
|
||||
{
|
||||
struct in_addr alias_addr;
|
||||
|
||||
alias_addr = FindAliasAddress(src_addr);
|
||||
link = AddLink(src_addr, dst_addr, alias_addr,
|
||||
src_port, 0, alias_port,
|
||||
link_type);
|
||||
}
|
||||
|
||||
return(link);
|
||||
}
|
||||
|
||||
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct in_addr alias_addr)
|
||||
{
|
||||
|
@ -113,6 +113,15 @@ FindPptpIn(struct in_addr, struct in_addr, u_short);
|
||||
struct alias_link *
|
||||
FindPptpOut(struct in_addr, struct in_addr, u_short);
|
||||
|
||||
struct alias_link *
|
||||
QueryUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
|
||||
struct alias_link *
|
||||
QueryUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
|
||||
struct alias_link *
|
||||
FindRtspOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
|
||||
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct in_addr);
|
||||
|
||||
@ -120,6 +129,8 @@ struct in_addr
|
||||
FindAliasAddress(struct in_addr);
|
||||
|
||||
/* External data access/modification */
|
||||
int FindNewPortGroup(struct in_addr, struct in_addr,
|
||||
u_short, u_short, u_short, u_char, u_char);
|
||||
void GetFragmentAddr(struct alias_link *, struct in_addr *);
|
||||
void SetFragmentAddr(struct alias_link *, struct in_addr);
|
||||
void GetFragmentPtr(struct alias_link *, char **);
|
||||
@ -165,6 +176,9 @@ void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
|
||||
/* IRC routines */
|
||||
void AliasHandleIrcOut(struct ip *, struct alias_link *, int);
|
||||
|
||||
/* RTSP routines */
|
||||
void AliasHandleRtspOut(struct ip *, struct alias_link *, int);
|
||||
|
||||
/* PPTP routines */
|
||||
int PptpGetCallID(struct ip *, u_short *);
|
||||
void PptpSetCallID(struct ip *, u_short);
|
||||
|
427
sys/netinet/libalias/alias_smedia.c
Normal file
427
sys/netinet/libalias/alias_smedia.c
Normal file
@ -0,0 +1,427 @@
|
||||
/*
|
||||
* alias_smedia.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.
|
||||
*
|
||||
* Copyright (c) 2000 Junichi SATOH <junichi@astec.co.jp>
|
||||
* <junichi@junichi.org>
|
||||
* 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.
|
||||
*
|
||||
* Authors: Erik Salander <erik@whistle.com>
|
||||
* Junichi SATOH <junichi@astec.co.jp>
|
||||
* <junichi@junichi.org>
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
Alias_smedia.c is meant to contain the aliasing code for streaming media
|
||||
protocols. It performs special processing for RSTP sessions under TCP.
|
||||
Specifically, when a SETUP request is sent by a client, or a 200 reply
|
||||
is sent by a server, it is intercepted and modified. The address is
|
||||
changed to the gateway machine and an aliasing port is used.
|
||||
|
||||
More specifically, the "client_port" configuration parameter is
|
||||
parsed for SETUP requests. The "server_port" configuration parameter is
|
||||
parsed for 200 replies eminating from a server. This is intended to handle
|
||||
the unicast case.
|
||||
|
||||
RTSP also allows a redirection of a stream to another client by using the
|
||||
"destination" configuration parameter. The destination config parm would
|
||||
indicate a different IP address. This function is NOT supported by the
|
||||
RTSP translation code below.
|
||||
|
||||
The RTSP multicast functions without any address translation intervention.
|
||||
|
||||
For this routine to work, the SETUP/200 must fit entirely
|
||||
into a single TCP packet. This is typically the case, but exceptions
|
||||
can easily be envisioned under the actual specifications.
|
||||
|
||||
Probably the most troubling aspect of the approach taken here is
|
||||
that the new SETUP/200 will typically be a different length, and
|
||||
this causes a certain amount of bookkeeping to keep track of the
|
||||
changes of sequence and acknowledgment numbers, since the client
|
||||
machine is totally unaware of the modification to the TCP stream.
|
||||
|
||||
Initial version: May, 2000 (eds)
|
||||
*/
|
||||
|
||||
#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 <netinet/udp.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
#define RTSP_CONTROL_PORT_NUMBER_1 554
|
||||
#define RTSP_CONTROL_PORT_NUMBER_2 7070
|
||||
#define RTSP_PORT_GROUP 2
|
||||
|
||||
#define ISDIGIT(a) (((a) >= '0') && ((a) <= '9'))
|
||||
|
||||
int search_string(char *data, int dlen, char *search_str)
|
||||
{
|
||||
int i, j, k;
|
||||
int search_str_len;
|
||||
|
||||
search_str_len = strlen(search_str);
|
||||
for (i = 0; i < dlen - search_str_len; i++) {
|
||||
for (j = i, k = 0; j < dlen - search_str_len; j++, k++) {
|
||||
if (data[j] != search_str[k] &&
|
||||
data[j] != search_str[k] - ('a' - 'A')) {
|
||||
break;
|
||||
}
|
||||
if (k == search_str_len - 1) {
|
||||
return j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int alias_rtsp_out(struct ip *pip,
|
||||
struct alias_link *link,
|
||||
char *data,
|
||||
char *port_str)
|
||||
{
|
||||
int hlen, tlen, dlen;
|
||||
struct tcphdr *tc;
|
||||
int i, j, pos, state, port_dlen, new_dlen, delta;
|
||||
u_short p[2], new_len;
|
||||
u_short sport, eport, base_port;
|
||||
u_short salias = 0, ealias = 0, base_alias = 0;
|
||||
char *transport_str = "transport:";
|
||||
char newdata[2048], *port_data, *port_newdata, stemp[80];
|
||||
int links_created = 0, pkt_updated = 0;
|
||||
struct alias_link *rtsp_link = NULL;
|
||||
struct in_addr null_addr;
|
||||
|
||||
/* Calculate data length of TCP packet */
|
||||
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;
|
||||
|
||||
/* Find keyword, "Transport: " */
|
||||
pos = search_string(data, dlen, transport_str);
|
||||
if (pos < 0) {
|
||||
return -1;
|
||||
}
|
||||
port_data = data + pos;
|
||||
port_dlen = dlen - pos;
|
||||
|
||||
memcpy(newdata, data, pos);
|
||||
port_newdata = newdata + pos;
|
||||
|
||||
while (port_dlen > strlen(port_str)) {
|
||||
/* Find keyword, appropriate port string */
|
||||
pos = search_string(port_data, port_dlen, port_str);
|
||||
if (pos < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy (port_newdata, port_data, pos + 1);
|
||||
port_newdata += (pos + 1);
|
||||
|
||||
p[0] = p[1] = 0;
|
||||
sport = eport = 0;
|
||||
state = 0;
|
||||
for (i = pos; i < port_dlen; i++) {
|
||||
switch(state) {
|
||||
case 0:
|
||||
if (port_data[i] == '=') {
|
||||
state++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (ISDIGIT(port_data[i])) {
|
||||
p[0] = p[0] * 10 + port_data[i] - '0';
|
||||
} else {
|
||||
if (port_data[i] == ';') {
|
||||
state = 3;
|
||||
}
|
||||
if (port_data[i] == '-') {
|
||||
state++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (ISDIGIT(port_data[i])) {
|
||||
p[1] = p[1] * 10 + port_data[i] - '0';
|
||||
} else {
|
||||
state++;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
base_port = p[0];
|
||||
sport = htons(p[0]);
|
||||
eport = htons(p[1]);
|
||||
|
||||
if (!links_created) {
|
||||
|
||||
links_created = 1;
|
||||
/* Find an even numbered port number base that
|
||||
satisfies the contiguous number of ports we need */
|
||||
null_addr.s_addr = 0;
|
||||
if (0 == (salias = FindNewPortGroup(null_addr,
|
||||
FindAliasAddress(pip->ip_src),
|
||||
sport, 0,
|
||||
RTSP_PORT_GROUP,
|
||||
IPPROTO_UDP, 1))) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/RTSP: Cannot find contiguous RTSP data ports\n");
|
||||
#endif
|
||||
} else {
|
||||
|
||||
base_alias = ntohs(salias);
|
||||
for (j = 0; j < RTSP_PORT_GROUP; j++) {
|
||||
/* Establish link to port found in RTSP packet */
|
||||
rtsp_link = FindRtspOut(GetOriginalAddress(link), null_addr,
|
||||
htons(base_port + j), htons(base_alias + j),
|
||||
IPPROTO_UDP);
|
||||
if (rtsp_link != NULL) {
|
||||
#ifndef NO_FW_PUNCH
|
||||
/* Punch hole in firewall */
|
||||
PunchFWHole(rtsp_link);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/RTSP: Cannot allocate RTSP data ports\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ealias = htons(base_alias + (RTSP_PORT_GROUP - 1));
|
||||
}
|
||||
|
||||
if (salias && rtsp_link) {
|
||||
|
||||
pkt_updated = 1;
|
||||
|
||||
/* Copy into IP packet */
|
||||
sprintf(stemp, "%d", ntohs(salias));
|
||||
memcpy(port_newdata, stemp, strlen(stemp));
|
||||
port_newdata += strlen(stemp);
|
||||
|
||||
if (eport != 0) {
|
||||
*port_newdata = '-';
|
||||
port_newdata++;
|
||||
|
||||
/* Copy into IP packet */
|
||||
sprintf(stemp, "%d", ntohs(ealias));
|
||||
memcpy(port_newdata, stemp, strlen(stemp));
|
||||
port_newdata += strlen(stemp);
|
||||
}
|
||||
|
||||
*port_newdata = ';';
|
||||
port_newdata++;
|
||||
}
|
||||
state++;
|
||||
break;
|
||||
}
|
||||
if (state > 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
port_data += i;
|
||||
port_dlen -= i;
|
||||
}
|
||||
|
||||
if (!pkt_updated)
|
||||
return -1;
|
||||
|
||||
memcpy (port_newdata, port_data, port_dlen);
|
||||
port_newdata += port_dlen;
|
||||
*port_newdata = '\0';
|
||||
|
||||
/* Create new packet */
|
||||
new_dlen = port_newdata - newdata;
|
||||
memcpy (data, newdata, new_dlen);
|
||||
|
||||
SetAckModified(link);
|
||||
delta = GetDeltaSeqOut(pip, link);
|
||||
AddSeq(pip, link, delta + new_dlen - dlen);
|
||||
|
||||
new_len = htons(hlen + new_dlen);
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
&new_len,
|
||||
&pip->ip_len,
|
||||
1);
|
||||
pip->ip_len = new_len;
|
||||
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Support the protocol used by early versions of RealPlayer */
|
||||
|
||||
int alias_pna_out(struct ip *pip,
|
||||
struct alias_link *link,
|
||||
char *data,
|
||||
int dlen)
|
||||
{
|
||||
struct alias_link *pna_links;
|
||||
u_short msg_id, msg_len;
|
||||
char *work;
|
||||
u_short alias_port, port;
|
||||
struct tcphdr *tc;
|
||||
|
||||
work = data;
|
||||
work += 5;
|
||||
while (work + 4 < data + dlen) {
|
||||
memcpy(&msg_id, work, 2);
|
||||
work += 2;
|
||||
memcpy(&msg_len, work, 2);
|
||||
work += 2;
|
||||
if (ntohs(msg_id) == 0) {
|
||||
/* end of options */
|
||||
return 0;
|
||||
}
|
||||
if ((ntohs(msg_id) == 1) || (ntohs(msg_id) == 7)) {
|
||||
memcpy((char*)&port, (char*)work, 2);
|
||||
pna_links = FindUdpTcpOut(pip->ip_src, GetDestAddress(link),
|
||||
port, 0, IPPROTO_UDP);
|
||||
if (pna_links != NULL) {
|
||||
#ifndef NO_FW_PUNCH
|
||||
/* Punch hole in firewall */
|
||||
PunchFWHole(pna_links);
|
||||
#endif
|
||||
tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
|
||||
alias_port = GetAliasPort(pna_links);
|
||||
memcpy((char*)work, (char*)&alias_port, 2);
|
||||
|
||||
/* Compute TCP checksum for revised packet */
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
}
|
||||
}
|
||||
work += ntohs(msg_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
AliasHandleRtspOut(struct ip *pip, struct alias_link *link, int maxpacketsize)
|
||||
{
|
||||
int hlen, tlen, dlen;
|
||||
struct tcphdr *tc;
|
||||
char *data, *setup = "SETUP", *pna = "PNA", *str200 = "200", *okstr = "OK";
|
||||
char *client_port_str = "client_port", *server_port_str = "server_port";
|
||||
int i, parseOk;
|
||||
|
||||
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;
|
||||
|
||||
data = (char*)pip;
|
||||
data += hlen;
|
||||
|
||||
/* When aliasing a client, check for the SETUP request */
|
||||
if ((ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1) ||
|
||||
(ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2)) {
|
||||
|
||||
if (dlen >= strlen(setup)) {
|
||||
if (memcmp(data, setup, strlen(setup)) == 0) {
|
||||
alias_rtsp_out(pip, link, data, client_port_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dlen >= strlen(pna)) {
|
||||
if (memcmp(data, pna, strlen(pna)) == 0) {
|
||||
alias_pna_out(pip, link, data, dlen);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* When aliasing a server, check for the 200 reply
|
||||
Accomodate varying number of blanks between 200 & OK */
|
||||
|
||||
if (dlen >= strlen(str200)) {
|
||||
|
||||
for (parseOk = 0, i = 0;
|
||||
i <= dlen - strlen(str200);
|
||||
i++) {
|
||||
if (memcmp(&data[i], str200, strlen(str200)) == 0) {
|
||||
parseOk = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parseOk) {
|
||||
|
||||
i += strlen(str200); /* skip string found */
|
||||
while(data[i] == ' ') /* skip blank(s) */
|
||||
i++;
|
||||
|
||||
if ((dlen - i) >= strlen(okstr)) {
|
||||
|
||||
if (memcmp(&data[i], okstr, strlen(okstr)) == 0)
|
||||
alias_rtsp_out(pip, link, data, server_port_str);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -808,6 +808,25 @@ If the checksum is valid,
|
||||
.Fn PacketAliasInternetChecksum
|
||||
will return zero.
|
||||
.Ed
|
||||
.Pp
|
||||
.Ft int
|
||||
.Fn PacketUnaliasOut "char *buffer" "int maxpacketsize"
|
||||
.Bd -ragged -offset indent
|
||||
An outgoing packet, which has already been aliased, has its private address/port
|
||||
information restored by this function.
|
||||
The IP packet is pointed to by
|
||||
.Fa buffer ,
|
||||
and
|
||||
.Fa maxpacketsize
|
||||
is provided for error checking purposes.
|
||||
This function can be used if an already-aliased packet needs to have its
|
||||
original IP header restored for further processing (eg. logging).
|
||||
.Ed
|
||||
.Sh BUGS
|
||||
PPTP aliasing does not work when more than one internal client
|
||||
connects to the same external server at the same time, because
|
||||
PPTP requires a single TCP control connection to be established
|
||||
between any two IP addresses.
|
||||
.Sh AUTHORS
|
||||
.An Charles Mott Aq cmott@scientech.com ,
|
||||
versions 1.0 - 1.8, 2.0 - 2.4.
|
||||
@ -816,7 +835,9 @@ 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.
|
||||
added support for PPTP and RTSP.
|
||||
.An Junichi Satoh Aq junichi@junichi.org
|
||||
added support for RTSP/PNA.
|
||||
.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