Build userland libalias using src/sys/netinet/libalias.
Reviewed by: ru Repocopy by: peter
This commit is contained in:
parent
5542bd31ad
commit
c9c0d4d0d6
@ -1,145 +0,0 @@
|
||||
$FreeBSD$
|
||||
|
||||
Version 1.0: August 11, 1996 (cjm)
|
||||
|
||||
Version 1.1: August 20, 1996 (cjm)
|
||||
- Host accepts incoming connections for ports 0 to 1023.
|
||||
|
||||
Version 1.2: September 7, 1996 (cjm)
|
||||
- Fragment handling error in alias_db.c corrected.
|
||||
|
||||
Version 1.3: September 15, 1996 (cjm)
|
||||
- Generalized mechanism for handling incoming
|
||||
connections (no more 0 to 1023 restriction).
|
||||
|
||||
- Increased ICMP support (will handle traceroute now).
|
||||
|
||||
- Improved TCP close connection logic.
|
||||
|
||||
Version 1.4: September 16, 1996 (cjm)
|
||||
|
||||
Version 1.5: September 17, 1996 (cjm)
|
||||
- Corrected error in handling incoming UDP packets
|
||||
with zero checksum.
|
||||
|
||||
Version 1.6: September 18, 1996
|
||||
- Simplified ICMP data storage. Will now handle
|
||||
tracert from Win95 and NT as well as FreeBSD
|
||||
traceroute, which uses UDP packets to non-existent
|
||||
ports.
|
||||
|
||||
Version 1.7: January 9, 1997 (cjm)
|
||||
- Reduced malloc() activity for ICMP echo and
|
||||
timestamp requests.
|
||||
|
||||
- Added handling for out-of-order IP fragments.
|
||||
|
||||
- Switched to differential checksum computation
|
||||
for IP headers (TCP, UDP and ICMP checksums
|
||||
were already differential).
|
||||
|
||||
- Accepts FTP data connections from other than
|
||||
port 20. This allows one ftp connections
|
||||
from two hosts which are both running packet
|
||||
aliasing.
|
||||
|
||||
- Checksum error on FTP transfers. Problem
|
||||
in code located by Martin Renters and
|
||||
Brian Somers.
|
||||
|
||||
Version 1.8: January 14, 1997 (cjm)
|
||||
- Fixed data type error in function StartPoint()
|
||||
in alias_db.c (this bug did not exist before v1.7)
|
||||
Problem in code located by Ari Suutari.
|
||||
|
||||
Version 1.9: February 1, 1997 (Eivind Eklund <perhaps@yes.no>)
|
||||
- Added support for IRC DCC (ee)
|
||||
|
||||
- Changed the aliasing routines to use ANSI style
|
||||
throughout (ee)
|
||||
|
||||
- Minor API changes for integration with other
|
||||
programs than PPP (ee)
|
||||
|
||||
- Fixed minor security hole in alias_ftp.c for
|
||||
other applications of the aliasing software.
|
||||
Hole could _not_ manifest in ppp+pktAlias, but
|
||||
could potentially manifest in other applications
|
||||
of the aliasing. (ee)
|
||||
|
||||
- Connections initiated from packet aliasing
|
||||
host machine will not have their port number
|
||||
aliased unless it conflicts with an aliasing
|
||||
port already being used. (There is an option
|
||||
to disable this for debugging) (cjm)
|
||||
|
||||
- Sockets will be allocated in cases where
|
||||
there might be port interference with the
|
||||
host machine. This can be disabled in cases
|
||||
where the ppp host will be acting purely as a
|
||||
masquerading router and not generate any
|
||||
traffic of its own.
|
||||
(cjm)
|
||||
|
||||
Version 2.0: March, 1997 (cjm)
|
||||
- Aliasing links are cleared only when a host interface address
|
||||
changes.
|
||||
|
||||
- PacketAliasPermanentLink() API added.
|
||||
|
||||
- Option for only aliasing private, unregistered
|
||||
IP addresses added.
|
||||
|
||||
- Substantial rework to the aliasing lookup engine.
|
||||
|
||||
Version 2.1: May, 1997 (cjm)
|
||||
- Continuing rework to the aliasing lookup engine
|
||||
to support multiple incoming addresses and static
|
||||
NAT. PacketAliasRedirectPort() and
|
||||
PacketAliasRedirectAddr() added to API.
|
||||
|
||||
- Now supports outgoing as well as incoming ICMP
|
||||
error messages.
|
||||
|
||||
Version 2.2: July, 1997 (cjm)
|
||||
- Rationalized API function names to all begin with
|
||||
"PacketAlias..." Old function names are retained
|
||||
for backwards compatibility.
|
||||
|
||||
- Packet aliasing engine will now free memory of
|
||||
fragments which are never resolved after a timeout
|
||||
period. Once a fragment is resolved, it becomes
|
||||
the users responsibility to free the memory.
|
||||
|
||||
Version 2.3: August 11, 1997 (cjm)
|
||||
- Problem associated with socket file descriptor
|
||||
accumulation in alias_db.c corrected. The sockets
|
||||
had to be closed when a binding failed. Problem
|
||||
in code located by Gordon Burditt.
|
||||
|
||||
Version 2.4: September 1, 1997 (cjm)
|
||||
- PKT_ALIAS_UNREGISTERED_ONLY option repaired.
|
||||
This part of the code was incorrectly re-implemented
|
||||
in version 2.1.
|
||||
|
||||
Version 2.5: December, 1997 (ee)
|
||||
- Added PKT_ALIAS_PUNCH_FW mode for firewall
|
||||
bypass of FTP/IRC DCC data connections. Also added
|
||||
improved TCP connection monitoring.
|
||||
|
||||
Version 2.6: May, 1998 (amurai)
|
||||
- Added supporting routine for NetBios over TCP/IP.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
@ -1,5 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../sys/netinet/libalias
|
||||
|
||||
LIB= alias
|
||||
SHLIBDIR?= /lib
|
||||
SHLIB_MAJOR= 4
|
||||
|
1433
lib/libalias/alias.c
1433
lib/libalias/alias.c
File diff suppressed because it is too large
Load Diff
@ -1,265 +0,0 @@
|
||||
/* lint -save -library Flexelint comment for external headers */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 Charles Mott <cm@linktel.net>
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Alias.h defines the outside world interfaces for the packet aliasing
|
||||
* software.
|
||||
*
|
||||
* This software is placed into the public domain with no restrictions on its
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
#ifndef _ALIAS_H_
|
||||
#define _ALIAS_H_
|
||||
|
||||
/*
|
||||
* The external interface to libalias, the packet aliasing engine.
|
||||
*
|
||||
* There are two sets of functions:
|
||||
*
|
||||
* PacketAlias*() the old API which doesn't take an instance pointer
|
||||
* and therefore can only have one packet engine at a time.
|
||||
*
|
||||
* LibAlias*() the new API which takes as first argument a pointer to
|
||||
* the instance of the packet aliasing engine.
|
||||
*
|
||||
* The functions otherwise correspond to each other one for one, except
|
||||
* for the LibAliasUnaliasOut()/PacketUnaliasOut() function which were
|
||||
* were misnamed in the old API.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The instance structure
|
||||
*/
|
||||
struct libalias;
|
||||
|
||||
/*
|
||||
* An anonymous structure, a pointer to which is returned from
|
||||
* PacketAliasRedirectAddr(), PacketAliasRedirectPort() or
|
||||
* PacketAliasRedirectProto(), passed to PacketAliasAddServer(),
|
||||
* and freed by PacketAliasRedirectDelete().
|
||||
*/
|
||||
struct alias_link;
|
||||
|
||||
|
||||
/* OLD API */
|
||||
|
||||
/* Initialization and control functions. */
|
||||
void PacketAliasInit(void);
|
||||
void PacketAliasSetAddress(struct in_addr _addr);
|
||||
void PacketAliasSetFWBase(unsigned int _base, unsigned int _num);
|
||||
void PacketAliasSetSkinnyPort(unsigned int _port);
|
||||
unsigned int
|
||||
PacketAliasSetMode(unsigned int _flags, unsigned int _mask);
|
||||
void PacketAliasUninit(void);
|
||||
|
||||
/* Packet Handling functions. */
|
||||
int PacketAliasIn(char *_ptr, int _maxpacketsize);
|
||||
int PacketAliasOut(char *_ptr, int _maxpacketsize);
|
||||
int PacketUnaliasOut(char *_ptr, int _maxpacketsize);
|
||||
|
||||
/* Port and address redirection functions. */
|
||||
|
||||
|
||||
int
|
||||
PacketAliasAddServer(struct alias_link *_lnk,
|
||||
struct in_addr _addr, unsigned short _port);
|
||||
struct alias_link *
|
||||
PacketAliasRedirectAddr(struct in_addr _src_addr,
|
||||
struct in_addr _alias_addr);
|
||||
int PacketAliasRedirectDynamic(struct alias_link *_lnk);
|
||||
void PacketAliasRedirectDelete(struct alias_link *_lnk);
|
||||
struct alias_link *
|
||||
PacketAliasRedirectPort(struct in_addr _src_addr,
|
||||
unsigned short _src_port, struct in_addr _dst_addr,
|
||||
unsigned short _dst_port, struct in_addr _alias_addr,
|
||||
unsigned short _alias_port, unsigned char _proto);
|
||||
struct alias_link *
|
||||
PacketAliasRedirectProto(struct in_addr _src_addr,
|
||||
struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
unsigned char _proto);
|
||||
|
||||
/* Fragment Handling functions. */
|
||||
void PacketAliasFragmentIn(char *_ptr, char *_ptr_fragment);
|
||||
char *PacketAliasGetFragment(char *_ptr);
|
||||
int PacketAliasSaveFragment(char *_ptr);
|
||||
|
||||
/* Miscellaneous functions. */
|
||||
int PacketAliasCheckNewLink(void);
|
||||
unsigned short
|
||||
PacketAliasInternetChecksum(unsigned short *_ptr, int _nbytes);
|
||||
void PacketAliasSetTarget(struct in_addr _target_addr);
|
||||
|
||||
/* Transparent proxying routines. */
|
||||
int PacketAliasProxyRule(const char *_cmd);
|
||||
|
||||
/* NEW API */
|
||||
|
||||
/* Initialization and control functions. */
|
||||
struct libalias *LibAliasInit(struct libalias *);
|
||||
void LibAliasSetAddress(struct libalias *, struct in_addr _addr);
|
||||
void LibAliasSetFWBase(struct libalias *, unsigned int _base, unsigned int _num);
|
||||
void LibAliasSetSkinnyPort(struct libalias *, unsigned int _port);
|
||||
unsigned int
|
||||
LibAliasSetMode(struct libalias *, unsigned int _flags, unsigned int _mask);
|
||||
void LibAliasUninit(struct libalias *);
|
||||
|
||||
/* Packet Handling functions. */
|
||||
int LibAliasIn (struct libalias *, char *_ptr, int _maxpacketsize);
|
||||
int LibAliasOut(struct libalias *, char *_ptr, int _maxpacketsize);
|
||||
int LibAliasOutTry(struct libalias *, char *_ptr, int _maxpacketsize, int _create);
|
||||
int LibAliasUnaliasOut(struct libalias *, char *_ptr, int _maxpacketsize);
|
||||
|
||||
/* Port and address redirection functions. */
|
||||
|
||||
int
|
||||
LibAliasAddServer(struct libalias *, struct alias_link *_lnk,
|
||||
struct in_addr _addr, unsigned short _port);
|
||||
struct alias_link *
|
||||
LibAliasRedirectAddr(struct libalias *, struct in_addr _src_addr,
|
||||
struct in_addr _alias_addr);
|
||||
int LibAliasRedirectDynamic(struct libalias *, struct alias_link *_lnk);
|
||||
void LibAliasRedirectDelete(struct libalias *, struct alias_link *_lnk);
|
||||
struct alias_link *
|
||||
LibAliasRedirectPort(struct libalias *, struct in_addr _src_addr,
|
||||
unsigned short _src_port, struct in_addr _dst_addr,
|
||||
unsigned short _dst_port, struct in_addr _alias_addr,
|
||||
unsigned short _alias_port, unsigned char _proto);
|
||||
struct alias_link *
|
||||
LibAliasRedirectProto(struct libalias *, struct in_addr _src_addr,
|
||||
struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
unsigned char _proto);
|
||||
|
||||
/* Fragment Handling functions. */
|
||||
void LibAliasFragmentIn(struct libalias *, char *_ptr, char *_ptr_fragment);
|
||||
char *LibAliasGetFragment(struct libalias *, char *_ptr);
|
||||
int LibAliasSaveFragment(struct libalias *, char *_ptr);
|
||||
|
||||
/* Miscellaneous functions. */
|
||||
int LibAliasCheckNewLink(struct libalias *);
|
||||
unsigned short
|
||||
LibAliasInternetChecksum(struct libalias *, unsigned short *_ptr, int _nbytes);
|
||||
void LibAliasSetTarget(struct libalias *, struct in_addr _target_addr);
|
||||
|
||||
/* Transparent proxying routines. */
|
||||
int LibAliasProxyRule(struct libalias *, const char *_cmd);
|
||||
|
||||
|
||||
/*
|
||||
* Mode flags and other constants.
|
||||
*/
|
||||
|
||||
|
||||
/* Mode flags, set using PacketAliasSetMode() */
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_LOG is set, a message will be printed to /var/log/alias.log
|
||||
* every time a link is created or deleted. This is useful for debugging.
|
||||
*/
|
||||
#define PKT_ALIAS_LOG 0x01
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g. to ftp,
|
||||
* telnet or web servers will be prevented by the aliasing mechanism.
|
||||
*/
|
||||
#define PKT_ALIAS_DENY_INCOMING 0x02
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_SAME_PORTS is set, packets will be attempted sent from the
|
||||
* same port as they originated on. This allows e.g. rsh to work *99% of the
|
||||
* time*, but _not_ 100% (it will be slightly flakey instead of not working
|
||||
* at all). This mode bit is set by PacketAliasInit(), so it is a default
|
||||
* mode of operation.
|
||||
*/
|
||||
#define PKT_ALIAS_SAME_PORTS 0x04
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_USE_SOCKETS is set, then when partially specified links (e.g.
|
||||
* destination port and/or address is zero), the packet aliasing engine will
|
||||
* attempt to allocate a socket for the aliasing port it chooses. This will
|
||||
* avoid interference with the host machine. Fully specified links do not
|
||||
* require this. This bit is set after a call to PacketAliasInit(), so it is
|
||||
* a default mode of operation.
|
||||
*/
|
||||
#define PKT_ALIAS_USE_SOCKETS 0x08
|
||||
|
||||
/*-
|
||||
* If PKT_ALIAS_UNREGISTERED_ONLY is set, then only packets with
|
||||
* unregistered source addresses will be aliased. Private
|
||||
* addresses are those in the following ranges:
|
||||
*
|
||||
* 10.0.0.0 -> 10.255.255.255
|
||||
* 172.16.0.0 -> 172.31.255.255
|
||||
* 192.168.0.0 -> 192.168.255.255
|
||||
*/
|
||||
#define PKT_ALIAS_UNREGISTERED_ONLY 0x10
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_RESET_ON_ADDR_CHANGE is set, then the table of dynamic
|
||||
* aliasing links will be reset whenever PacketAliasSetAddress() changes the
|
||||
* default aliasing address. If the default aliasing address is left
|
||||
* unchanged by this function call, then the table of dynamic aliasing links
|
||||
* will be left intact. This bit is set after a call to PacketAliasInit().
|
||||
*/
|
||||
#define PKT_ALIAS_RESET_ON_ADDR_CHANGE 0x20
|
||||
|
||||
#ifndef NO_FW_PUNCH
|
||||
/*
|
||||
* If PKT_ALIAS_PUNCH_FW is set, active FTP and IRC DCC connections will
|
||||
* create a 'hole' in the firewall to allow the transfers to work. The
|
||||
* ipfw rule number that the hole is created with is controlled by
|
||||
* PacketAliasSetFWBase(). The hole will be attached to that
|
||||
* particular alias_link, so when the link goes away the hole is deleted.
|
||||
*/
|
||||
#define PKT_ALIAS_PUNCH_FW 0x100
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_PROXY_ONLY is set, then NAT will be disabled and only
|
||||
* transparent proxying is performed.
|
||||
*/
|
||||
#define PKT_ALIAS_PROXY_ONLY 0x40
|
||||
|
||||
/*
|
||||
* If PKT_ALIAS_REVERSE is set, the actions of PacketAliasIn() and
|
||||
* PacketAliasOut() are reversed.
|
||||
*/
|
||||
#define PKT_ALIAS_REVERSE 0x80
|
||||
|
||||
/* Function return codes. */
|
||||
#define PKT_ALIAS_ERROR -1
|
||||
#define PKT_ALIAS_OK 1
|
||||
#define PKT_ALIAS_IGNORED 2
|
||||
#define PKT_ALIAS_UNRESOLVED_FRAGMENT 3
|
||||
#define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4
|
||||
|
||||
#endif /* !_ALIAS_H_ */
|
||||
|
||||
/* lint -restore */
|
@ -1,123 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
|
||||
* with the aid of code written by
|
||||
* Junichi SATOH <junichi@astec.co.jp> 1996, 1997.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
/* CU-SeeMe Data Header */
|
||||
struct cu_header {
|
||||
u_int16_t dest_family;
|
||||
u_int16_t dest_port;
|
||||
u_int32_t dest_addr;
|
||||
int16_t family;
|
||||
u_int16_t port;
|
||||
u_int32_t addr;
|
||||
u_int32_t seq;
|
||||
u_int16_t msg;
|
||||
u_int16_t data_type;
|
||||
u_int16_t packet_len;
|
||||
};
|
||||
|
||||
/* Open Continue Header */
|
||||
struct oc_header {
|
||||
u_int16_t client_count; /* Number of client info structs */
|
||||
u_int32_t seq_no;
|
||||
char user_name [20];
|
||||
char reserved [4]; /* flags, version stuff, etc */
|
||||
};
|
||||
|
||||
/* client info structures */
|
||||
struct client_info {
|
||||
u_int32_t address;/* Client address */
|
||||
char reserved [8]; /* Flags, pruning bitfield, packet
|
||||
* counts etc */
|
||||
};
|
||||
|
||||
void
|
||||
AliasHandleCUSeeMeOut(struct libalias *la, struct ip *pip, struct alias_link *lnk)
|
||||
{
|
||||
struct udphdr *ud = ip_next(pip);
|
||||
|
||||
if (ntohs(ud->uh_ulen) - sizeof(struct udphdr) >= sizeof(struct cu_header)) {
|
||||
struct cu_header *cu;
|
||||
struct alias_link *cu_lnk;
|
||||
|
||||
cu = udp_next(ud);
|
||||
if (cu->addr)
|
||||
cu->addr = (u_int32_t) GetAliasAddress(lnk).s_addr;
|
||||
|
||||
cu_lnk = FindUdpTcpOut(la, pip->ip_src, GetDestAddress(lnk),
|
||||
ud->uh_dport, 0, IPPROTO_UDP, 1);
|
||||
|
||||
#ifndef NO_FW_PUNCH
|
||||
if (cu_lnk)
|
||||
PunchFWHole(cu_lnk);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AliasHandleCUSeeMeIn(struct libalias *la, struct ip *pip, struct in_addr original_addr)
|
||||
{
|
||||
struct in_addr alias_addr;
|
||||
struct udphdr *ud;
|
||||
struct cu_header *cu;
|
||||
struct oc_header *oc;
|
||||
struct client_info *ci;
|
||||
char *end;
|
||||
int i;
|
||||
|
||||
(void)la;
|
||||
alias_addr.s_addr = pip->ip_dst.s_addr;
|
||||
ud = ip_next(pip);
|
||||
cu = udp_next(ud);
|
||||
oc = (struct oc_header *)(cu + 1);
|
||||
ci = (struct client_info *)(oc + 1);
|
||||
end = (char *)ud + ntohs(ud->uh_ulen);
|
||||
|
||||
if ((char *)oc <= end) {
|
||||
if (cu->dest_addr)
|
||||
cu->dest_addr = (u_int32_t) original_addr.s_addr;
|
||||
if (ntohs(cu->data_type) == 101)
|
||||
/* Find and change our address */
|
||||
for (i = 0; (char *)(ci + 1) <= end && i < oc->client_count; i++, ci++)
|
||||
if (ci->address == (u_int32_t) alias_addr.s_addr) {
|
||||
ci->address = (u_int32_t) original_addr.s_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,675 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Charles Mott <cm@linktel.net>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
Alias_ftp.c performs special processing for FTP sessions under
|
||||
TCP. Specifically, when a PORT/EPRT command from the client
|
||||
side or 227/229 reply from the server is sent, it is intercepted
|
||||
and modified. The address is changed to the gateway machine
|
||||
and an aliasing port is used.
|
||||
|
||||
For this routine to work, the message 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 message 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.
|
||||
|
||||
|
||||
References: RFC 959, RFC 2428.
|
||||
|
||||
Initial version: August, 1996 (cjm)
|
||||
|
||||
Version 1.6
|
||||
Brian Somers and Martin Renters identified an IP checksum
|
||||
error for modified IP packets.
|
||||
|
||||
Version 1.7: January 9, 1996 (cjm)
|
||||
Differential checksum computation for change
|
||||
in IP packet length.
|
||||
|
||||
Version 2.1: May, 1997 (cjm)
|
||||
Very minor changes to conform with
|
||||
local/global/function naming conventions
|
||||
within the packet aliasing module.
|
||||
|
||||
Version 3.1: May, 2000 (eds)
|
||||
Add support for passive mode, alias the 227 replies.
|
||||
|
||||
See HISTORY file for record of revisions.
|
||||
*/
|
||||
|
||||
/* 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"
|
||||
|
||||
#define FTP_CONTROL_PORT_NUMBER 21
|
||||
#define MAX_MESSAGE_SIZE 128
|
||||
|
||||
/* FTP protocol flags. */
|
||||
#define WAIT_CRLF 0x01
|
||||
|
||||
enum ftp_message_type {
|
||||
FTP_PORT_COMMAND,
|
||||
FTP_EPRT_COMMAND,
|
||||
FTP_227_REPLY,
|
||||
FTP_229_REPLY,
|
||||
FTP_UNKNOWN_MESSAGE
|
||||
};
|
||||
|
||||
static int ParseFtpPortCommand(struct libalias *la, char *, int);
|
||||
static int ParseFtpEprtCommand(struct libalias *la, char *, int);
|
||||
static int ParseFtp227Reply(struct libalias *la, char *, int);
|
||||
static int ParseFtp229Reply(struct libalias *la, char *, int);
|
||||
static void NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int);
|
||||
|
||||
void
|
||||
AliasHandleFtpOut(
|
||||
struct libalias *la,
|
||||
struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *lnk, /* The link to go through (aliased port) */
|
||||
int maxpacketsize /* The maximum size this packet can grow to
|
||||
(including headers) */ )
|
||||
{
|
||||
int hlen, tlen, dlen, pflags;
|
||||
char *sptr;
|
||||
struct tcphdr *tc;
|
||||
int ftp_message_type;
|
||||
|
||||
/* Calculate data length of TCP packet */
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
tlen = ntohs(pip->ip_len);
|
||||
dlen = tlen - hlen;
|
||||
|
||||
/* Place string pointer and beginning of data */
|
||||
sptr = (char *)pip;
|
||||
sptr += hlen;
|
||||
|
||||
/*
|
||||
* Check that data length is not too long and previous message was
|
||||
* properly terminated with CRLF.
|
||||
*/
|
||||
pflags = GetProtocolFlags(lnk);
|
||||
if (dlen <= MAX_MESSAGE_SIZE && !(pflags & WAIT_CRLF)) {
|
||||
ftp_message_type = FTP_UNKNOWN_MESSAGE;
|
||||
|
||||
if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) {
|
||||
/*
|
||||
* When aliasing a client, check for the PORT/EPRT command.
|
||||
*/
|
||||
if (ParseFtpPortCommand(la, sptr, dlen))
|
||||
ftp_message_type = FTP_PORT_COMMAND;
|
||||
else if (ParseFtpEprtCommand(la, sptr, dlen))
|
||||
ftp_message_type = FTP_EPRT_COMMAND;
|
||||
} else {
|
||||
/*
|
||||
* When aliasing a server, check for the 227/229 reply.
|
||||
*/
|
||||
if (ParseFtp227Reply(la, sptr, dlen))
|
||||
ftp_message_type = FTP_227_REPLY;
|
||||
else if (ParseFtp229Reply(la, sptr, dlen)) {
|
||||
ftp_message_type = FTP_229_REPLY;
|
||||
la->true_addr.s_addr = pip->ip_src.s_addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (ftp_message_type != FTP_UNKNOWN_MESSAGE)
|
||||
NewFtpMessage(la, pip, lnk, maxpacketsize, ftp_message_type);
|
||||
}
|
||||
/* Track the msgs which are CRLF term'd for PORT/PASV FW breach */
|
||||
|
||||
if (dlen) { /* only if there's data */
|
||||
sptr = (char *)pip; /* start over at beginning */
|
||||
tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may
|
||||
* have grown */
|
||||
if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n')
|
||||
pflags &= ~WAIT_CRLF;
|
||||
else
|
||||
pflags |= WAIT_CRLF;
|
||||
SetProtocolFlags(lnk, pflags);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
|
||||
{
|
||||
char ch;
|
||||
int i, state;
|
||||
u_int32_t addr;
|
||||
u_short port;
|
||||
u_int8_t octet;
|
||||
|
||||
/* Format: "PORT A,D,D,R,PO,RT". */
|
||||
|
||||
/* Return if data length is too short. */
|
||||
if (dlen < 18)
|
||||
return (0);
|
||||
|
||||
addr = port = octet = 0;
|
||||
state = -4;
|
||||
for (i = 0; i < dlen; i++) {
|
||||
ch = sptr[i];
|
||||
switch (state) {
|
||||
case -4:
|
||||
if (ch == 'P')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -3:
|
||||
if (ch == 'O')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -2:
|
||||
if (ch == 'R')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -1:
|
||||
if (ch == 'T')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (isspace(ch))
|
||||
break;
|
||||
else
|
||||
state++;
|
||||
case 1:
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
case 9:
|
||||
case 11:
|
||||
if (isdigit(ch)) {
|
||||
octet = ch - '0';
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 8:
|
||||
if (isdigit(ch))
|
||||
octet = 10 * octet + ch - '0';
|
||||
else if (ch == ',') {
|
||||
addr = (addr << 8) + octet;
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
case 10:
|
||||
case 12:
|
||||
if (isdigit(ch))
|
||||
octet = 10 * octet + ch - '0';
|
||||
else if (ch == ',' || state == 12) {
|
||||
port = (port << 8) + octet;
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == 13) {
|
||||
la->true_addr.s_addr = htonl(addr);
|
||||
la->true_port = port;
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ParseFtpEprtCommand(struct libalias *la, char *sptr, int dlen)
|
||||
{
|
||||
char ch, delim;
|
||||
int i, state;
|
||||
u_int32_t addr;
|
||||
u_short port;
|
||||
u_int8_t octet;
|
||||
|
||||
/* Format: "EPRT |1|A.D.D.R|PORT|". */
|
||||
|
||||
/* Return if data length is too short. */
|
||||
if (dlen < 18)
|
||||
return (0);
|
||||
|
||||
addr = port = octet = 0;
|
||||
delim = '|'; /* XXX gcc -Wuninitialized */
|
||||
state = -4;
|
||||
for (i = 0; i < dlen; i++) {
|
||||
ch = sptr[i];
|
||||
switch (state) {
|
||||
case -4:
|
||||
if (ch == 'E')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -3:
|
||||
if (ch == 'P')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -2:
|
||||
if (ch == 'R')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -1:
|
||||
if (ch == 'T')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (!isspace(ch)) {
|
||||
delim = ch;
|
||||
state++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (ch == '1') /* IPv4 address */
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case 2:
|
||||
if (ch == delim)
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
case 9:
|
||||
if (isdigit(ch)) {
|
||||
octet = ch - '0';
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
case 8:
|
||||
case 10:
|
||||
if (isdigit(ch))
|
||||
octet = 10 * octet + ch - '0';
|
||||
else if (ch == '.' || state == 10) {
|
||||
addr = (addr << 8) + octet;
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
case 11:
|
||||
if (isdigit(ch)) {
|
||||
port = ch - '0';
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
case 12:
|
||||
if (isdigit(ch))
|
||||
port = 10 * port + ch - '0';
|
||||
else if (ch == delim)
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == 13) {
|
||||
la->true_addr.s_addr = htonl(addr);
|
||||
la->true_port = port;
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ParseFtp227Reply(struct libalias *la, char *sptr, int dlen)
|
||||
{
|
||||
char ch;
|
||||
int i, state;
|
||||
u_int32_t addr;
|
||||
u_short port;
|
||||
u_int8_t octet;
|
||||
|
||||
/* Format: "227 Entering Passive Mode (A,D,D,R,PO,RT)" */
|
||||
|
||||
/* Return if data length is too short. */
|
||||
if (dlen < 17)
|
||||
return (0);
|
||||
|
||||
addr = port = octet = 0;
|
||||
|
||||
state = -3;
|
||||
for (i = 0; i < dlen; i++) {
|
||||
ch = sptr[i];
|
||||
switch (state) {
|
||||
case -3:
|
||||
if (ch == '2')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -2:
|
||||
if (ch == '2')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -1:
|
||||
if (ch == '7')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (ch == '(')
|
||||
state++;
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
case 9:
|
||||
case 11:
|
||||
if (isdigit(ch)) {
|
||||
octet = ch - '0';
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 8:
|
||||
if (isdigit(ch))
|
||||
octet = 10 * octet + ch - '0';
|
||||
else if (ch == ',') {
|
||||
addr = (addr << 8) + octet;
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
case 10:
|
||||
case 12:
|
||||
if (isdigit(ch))
|
||||
octet = 10 * octet + ch - '0';
|
||||
else if (ch == ',' || (state == 12 && ch == ')')) {
|
||||
port = (port << 8) + octet;
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == 13) {
|
||||
la->true_port = port;
|
||||
la->true_addr.s_addr = htonl(addr);
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ParseFtp229Reply(struct libalias *la, char *sptr, int dlen)
|
||||
{
|
||||
char ch, delim;
|
||||
int i, state;
|
||||
u_short port;
|
||||
|
||||
/* Format: "229 Entering Extended Passive Mode (|||PORT|)" */
|
||||
|
||||
/* Return if data length is too short. */
|
||||
if (dlen < 11)
|
||||
return (0);
|
||||
|
||||
port = 0;
|
||||
delim = '|'; /* XXX gcc -Wuninitialized */
|
||||
|
||||
state = -3;
|
||||
for (i = 0; i < dlen; i++) {
|
||||
ch = sptr[i];
|
||||
switch (state) {
|
||||
case -3:
|
||||
if (ch == '2')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -2:
|
||||
if (ch == '2')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case -1:
|
||||
if (ch == '9')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (ch == '(')
|
||||
state++;
|
||||
break;
|
||||
case 1:
|
||||
delim = ch;
|
||||
state++;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
if (ch == delim)
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case 4:
|
||||
if (isdigit(ch)) {
|
||||
port = ch - '0';
|
||||
state++;
|
||||
} else
|
||||
return (0);
|
||||
break;
|
||||
case 5:
|
||||
if (isdigit(ch))
|
||||
port = 10 * port + ch - '0';
|
||||
else if (ch == delim)
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
case 6:
|
||||
if (ch == ')')
|
||||
state++;
|
||||
else
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == 7) {
|
||||
la->true_port = port;
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
NewFtpMessage(struct libalias *la, struct ip *pip,
|
||||
struct alias_link *lnk,
|
||||
int maxpacketsize,
|
||||
int ftp_message_type)
|
||||
{
|
||||
struct alias_link *ftp_lnk;
|
||||
|
||||
/* Security checks. */
|
||||
if (pip->ip_src.s_addr != la->true_addr.s_addr)
|
||||
return;
|
||||
|
||||
if (la->true_port < IPPORT_RESERVED)
|
||||
return;
|
||||
|
||||
/* Establish link to address and port found in FTP control message. */
|
||||
ftp_lnk = FindUdpTcpOut(la, la->true_addr, GetDestAddress(lnk),
|
||||
htons(la->true_port), 0, IPPROTO_TCP, 1);
|
||||
|
||||
if (ftp_lnk != NULL) {
|
||||
int slen, hlen, tlen, dlen;
|
||||
struct tcphdr *tc;
|
||||
|
||||
#ifndef NO_FW_PUNCH
|
||||
/* Punch hole in firewall */
|
||||
PunchFWHole(ftp_lnk);
|
||||
#endif
|
||||
|
||||
/* Calculate data length of TCP packet */
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
tlen = ntohs(pip->ip_len);
|
||||
dlen = tlen - hlen;
|
||||
|
||||
/* Create new FTP message. */
|
||||
{
|
||||
char stemp[MAX_MESSAGE_SIZE + 1];
|
||||
char *sptr;
|
||||
u_short alias_port;
|
||||
u_char *ptr;
|
||||
int a1, a2, a3, a4, p1, p2;
|
||||
struct in_addr alias_address;
|
||||
|
||||
/* Decompose alias address into quad format */
|
||||
alias_address = GetAliasAddress(lnk);
|
||||
ptr = (u_char *) & alias_address.s_addr;
|
||||
a1 = *ptr++;
|
||||
a2 = *ptr++;
|
||||
a3 = *ptr++;
|
||||
a4 = *ptr;
|
||||
|
||||
alias_port = GetAliasPort(ftp_lnk);
|
||||
|
||||
switch (ftp_message_type) {
|
||||
case FTP_PORT_COMMAND:
|
||||
case FTP_227_REPLY:
|
||||
/* Decompose alias port into pair format. */
|
||||
ptr = (char *)&alias_port;
|
||||
p1 = *ptr++;
|
||||
p2 = *ptr;
|
||||
|
||||
if (ftp_message_type == FTP_PORT_COMMAND) {
|
||||
/* Generate PORT command string. */
|
||||
sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
|
||||
a1, a2, a3, a4, p1, p2);
|
||||
} else {
|
||||
/* Generate 227 reply string. */
|
||||
sprintf(stemp,
|
||||
"227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
|
||||
a1, a2, a3, a4, p1, p2);
|
||||
}
|
||||
break;
|
||||
case FTP_EPRT_COMMAND:
|
||||
/* Generate EPRT command string. */
|
||||
sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n",
|
||||
a1, a2, a3, a4, ntohs(alias_port));
|
||||
break;
|
||||
case FTP_229_REPLY:
|
||||
/* Generate 229 reply string. */
|
||||
sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n",
|
||||
ntohs(alias_port));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Save string length for IP header modification */
|
||||
slen = strlen(stemp);
|
||||
|
||||
/* Copy modified buffer into IP packet. */
|
||||
sptr = (char *)pip;
|
||||
sptr += hlen;
|
||||
strncpy(sptr, stemp, maxpacketsize - hlen);
|
||||
}
|
||||
|
||||
/* Save information regarding modified seq and ack numbers */
|
||||
{
|
||||
int delta;
|
||||
|
||||
SetAckModified(lnk);
|
||||
delta = GetDeltaSeqOut(pip, lnk);
|
||||
AddSeq(pip, lnk, delta + slen - dlen);
|
||||
}
|
||||
|
||||
/* Revise IP header */
|
||||
{
|
||||
u_short new_len;
|
||||
|
||||
new_len = htons(hlen + slen);
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
&new_len,
|
||||
&pip->ip_len,
|
||||
1);
|
||||
pip->ip_len = new_len;
|
||||
}
|
||||
|
||||
/* Compute TCP checksum for revised packet */
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,386 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Charles Mott <cm@linktel.net>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* Alias_irc.c intercepts packages contain IRC CTCP commands, and
|
||||
changes DCC commands to export a port on the aliasing host instead
|
||||
of an aliased host.
|
||||
|
||||
For this routine to work, the DCC command must fit entirely into a
|
||||
single TCP packet. This will usually happen, but is not
|
||||
guaranteed.
|
||||
|
||||
The interception is likely to change the length of the packet.
|
||||
The handling of this is copied more-or-less verbatim from
|
||||
ftp_alias.c
|
||||
|
||||
Initial version: Eivind Eklund <perhaps@yes.no> (ee) 97-01-29
|
||||
|
||||
Version 2.1: May, 1997 (cjm)
|
||||
Very minor changes to conform with
|
||||
local/global/function naming conventions
|
||||
withing the packet alising module.
|
||||
*/
|
||||
|
||||
/* 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 <limits.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
/* Local defines */
|
||||
#define DBprintf(a)
|
||||
|
||||
|
||||
void
|
||||
AliasHandleIrcOut(struct libalias *la,
|
||||
struct ip *pip, /* IP packet to examine */
|
||||
struct alias_link *lnk, /* Which link are we on? */
|
||||
int maxsize /* Maximum size of IP packet including
|
||||
* headers */
|
||||
)
|
||||
{
|
||||
int hlen, tlen, dlen;
|
||||
struct in_addr true_addr;
|
||||
u_short true_port;
|
||||
char *sptr;
|
||||
struct tcphdr *tc;
|
||||
int i; /* Iterator through the source */
|
||||
|
||||
/* Calculate data length of TCP packet */
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
tlen = ntohs(pip->ip_len);
|
||||
dlen = tlen - hlen;
|
||||
|
||||
/*
|
||||
* Return if data length is too short - assume an entire PRIVMSG in
|
||||
* each packet.
|
||||
*/
|
||||
if (dlen < (int)sizeof(":A!a@n.n PRIVMSG A :aDCC 1 1a") - 1)
|
||||
return;
|
||||
|
||||
/* Place string pointer at beginning of data */
|
||||
sptr = (char *)pip;
|
||||
sptr += hlen;
|
||||
maxsize -= hlen; /* We're interested in maximum size of
|
||||
* data, not packet */
|
||||
|
||||
/* Search for a CTCP command [Note 1] */
|
||||
for (i = 0; i < dlen; i++) {
|
||||
if (sptr[i] == '\001')
|
||||
goto lFOUND_CTCP;
|
||||
}
|
||||
return; /* No CTCP commands in */
|
||||
/* Handle CTCP commands - the buffer may have to be copied */
|
||||
lFOUND_CTCP:
|
||||
{
|
||||
char newpacket[65536]; /* Estimate of maximum packet size
|
||||
* :) */
|
||||
unsigned int copyat = i; /* Same */
|
||||
unsigned int iCopy = 0; /* How much data have we written to
|
||||
* copy-back string? */
|
||||
unsigned long org_addr; /* Original IP address */
|
||||
unsigned short org_port; /* Original source port
|
||||
* address */
|
||||
|
||||
lCTCP_START:
|
||||
if (i >= dlen || iCopy >= sizeof(newpacket))
|
||||
goto lPACKET_DONE;
|
||||
newpacket[iCopy++] = sptr[i++]; /* Copy the CTCP start
|
||||
* character */
|
||||
/* Start of a CTCP */
|
||||
if (i + 4 >= dlen) /* Too short for DCC */
|
||||
goto lBAD_CTCP;
|
||||
if (sptr[i + 0] != 'D')
|
||||
goto lBAD_CTCP;
|
||||
if (sptr[i + 1] != 'C')
|
||||
goto lBAD_CTCP;
|
||||
if (sptr[i + 2] != 'C')
|
||||
goto lBAD_CTCP;
|
||||
if (sptr[i + 3] != ' ')
|
||||
goto lBAD_CTCP;
|
||||
/* We have a DCC command - handle it! */
|
||||
i += 4; /* Skip "DCC " */
|
||||
if (iCopy + 4 > sizeof(newpacket))
|
||||
goto lPACKET_DONE;
|
||||
newpacket[iCopy++] = 'D';
|
||||
newpacket[iCopy++] = 'C';
|
||||
newpacket[iCopy++] = 'C';
|
||||
newpacket[iCopy++] = ' ';
|
||||
|
||||
DBprintf(("Found DCC\n"));
|
||||
/*
|
||||
* Skip any extra spaces (should not occur according to
|
||||
* protocol, but DCC breaks CTCP protocol anyway
|
||||
*/
|
||||
while (sptr[i] == ' ') {
|
||||
if (++i >= dlen) {
|
||||
DBprintf(("DCC packet terminated in just spaces\n"));
|
||||
goto lPACKET_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
DBprintf(("Transferring command...\n"));
|
||||
while (sptr[i] != ' ') {
|
||||
newpacket[iCopy++] = sptr[i];
|
||||
if (++i >= dlen || iCopy >= sizeof(newpacket)) {
|
||||
DBprintf(("DCC packet terminated during command\n"));
|
||||
goto lPACKET_DONE;
|
||||
}
|
||||
}
|
||||
/* Copy _one_ space */
|
||||
if (i + 1 < dlen && iCopy < sizeof(newpacket))
|
||||
newpacket[iCopy++] = sptr[i++];
|
||||
|
||||
DBprintf(("Done command - removing spaces\n"));
|
||||
/*
|
||||
* Skip any extra spaces (should not occur according to
|
||||
* protocol, but DCC breaks CTCP protocol anyway
|
||||
*/
|
||||
while (sptr[i] == ' ') {
|
||||
if (++i >= dlen) {
|
||||
DBprintf(("DCC packet terminated in just spaces (post-command)\n"));
|
||||
goto lPACKET_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
DBprintf(("Transferring filename...\n"));
|
||||
while (sptr[i] != ' ') {
|
||||
newpacket[iCopy++] = sptr[i];
|
||||
if (++i >= dlen || iCopy >= sizeof(newpacket)) {
|
||||
DBprintf(("DCC packet terminated during filename\n"));
|
||||
goto lPACKET_DONE;
|
||||
}
|
||||
}
|
||||
/* Copy _one_ space */
|
||||
if (i + 1 < dlen && iCopy < sizeof(newpacket))
|
||||
newpacket[iCopy++] = sptr[i++];
|
||||
|
||||
DBprintf(("Done filename - removing spaces\n"));
|
||||
/*
|
||||
* Skip any extra spaces (should not occur according to
|
||||
* protocol, but DCC breaks CTCP protocol anyway
|
||||
*/
|
||||
while (sptr[i] == ' ') {
|
||||
if (++i >= dlen) {
|
||||
DBprintf(("DCC packet terminated in just spaces (post-filename)\n"));
|
||||
goto lPACKET_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
DBprintf(("Fetching IP address\n"));
|
||||
/* Fetch IP address */
|
||||
org_addr = 0;
|
||||
while (i < dlen && isdigit(sptr[i])) {
|
||||
if (org_addr > ULONG_MAX / 10UL) { /* Terminate on overflow */
|
||||
DBprintf(("DCC Address overflow (org_addr == 0x%08lx, next char %c\n", org_addr, sptr[i]));
|
||||
goto lBAD_CTCP;
|
||||
}
|
||||
org_addr *= 10;
|
||||
org_addr += sptr[i++] - '0';
|
||||
}
|
||||
DBprintf(("Skipping space\n"));
|
||||
if (i + 1 >= dlen || sptr[i] != ' ') {
|
||||
DBprintf(("Overflow (%d >= %d) or bad character (%02x) terminating IP address\n", i + 1, dlen, sptr[i]));
|
||||
goto lBAD_CTCP;
|
||||
}
|
||||
/*
|
||||
* Skip any extra spaces (should not occur according to
|
||||
* protocol, but DCC breaks CTCP protocol anyway, so we
|
||||
* might as well play it safe
|
||||
*/
|
||||
while (sptr[i] == ' ') {
|
||||
if (++i >= dlen) {
|
||||
DBprintf(("Packet failure - space overflow.\n"));
|
||||
goto lPACKET_DONE;
|
||||
}
|
||||
}
|
||||
DBprintf(("Fetching port number\n"));
|
||||
/* Fetch source port */
|
||||
org_port = 0;
|
||||
while (i < dlen && isdigit(sptr[i])) {
|
||||
if (org_port > 6554) { /* Terminate on overflow
|
||||
* (65536/10 rounded up */
|
||||
DBprintf(("DCC: port number overflow\n"));
|
||||
goto lBAD_CTCP;
|
||||
}
|
||||
org_port *= 10;
|
||||
org_port += sptr[i++] - '0';
|
||||
}
|
||||
/* Skip illegal addresses (or early termination) */
|
||||
if (i >= dlen || (sptr[i] != '\001' && sptr[i] != ' ')) {
|
||||
DBprintf(("Bad port termination\n"));
|
||||
goto lBAD_CTCP;
|
||||
}
|
||||
DBprintf(("Got IP %lu and port %u\n", org_addr, (unsigned)org_port));
|
||||
|
||||
/* We've got the address and port - now alias it */
|
||||
{
|
||||
struct alias_link *dcc_lnk;
|
||||
struct in_addr destaddr;
|
||||
|
||||
|
||||
true_port = htons(org_port);
|
||||
true_addr.s_addr = htonl(org_addr);
|
||||
destaddr.s_addr = 0;
|
||||
|
||||
/* Sanity/Security checking */
|
||||
if (!org_addr || !org_port ||
|
||||
pip->ip_src.s_addr != true_addr.s_addr ||
|
||||
org_port < IPPORT_RESERVED)
|
||||
goto lBAD_CTCP;
|
||||
|
||||
/*
|
||||
* Steal the FTP_DATA_PORT - it doesn't really
|
||||
* matter, and this would probably allow it through
|
||||
* at least _some_ firewalls.
|
||||
*/
|
||||
dcc_lnk = FindUdpTcpOut(la, true_addr, destaddr,
|
||||
true_port, 0,
|
||||
IPPROTO_TCP, 1);
|
||||
DBprintf(("Got a DCC link\n"));
|
||||
if (dcc_lnk) {
|
||||
struct in_addr alias_address; /* Address from aliasing */
|
||||
u_short alias_port; /* Port given by
|
||||
* aliasing */
|
||||
int n;
|
||||
|
||||
#ifndef NO_FW_PUNCH
|
||||
/* Generate firewall hole as appropriate */
|
||||
PunchFWHole(dcc_lnk);
|
||||
#endif
|
||||
|
||||
alias_address = GetAliasAddress(lnk);
|
||||
n = snprintf(&newpacket[iCopy],
|
||||
sizeof(newpacket) - iCopy,
|
||||
"%lu ", (u_long) htonl(alias_address.s_addr));
|
||||
if (n < 0) {
|
||||
DBprintf(("DCC packet construct failure.\n"));
|
||||
goto lBAD_CTCP;
|
||||
}
|
||||
if ((iCopy += n) >= sizeof(newpacket)) { /* Truncated/fit exactly
|
||||
* - bad news */
|
||||
DBprintf(("DCC constructed packet overflow.\n"));
|
||||
goto lBAD_CTCP;
|
||||
}
|
||||
alias_port = GetAliasPort(dcc_lnk);
|
||||
n = snprintf(&newpacket[iCopy],
|
||||
sizeof(newpacket) - iCopy,
|
||||
"%u", htons(alias_port));
|
||||
if (n < 0) {
|
||||
DBprintf(("DCC packet construct failure.\n"));
|
||||
goto lBAD_CTCP;
|
||||
}
|
||||
iCopy += n;
|
||||
/*
|
||||
* Done - truncated cases will be taken
|
||||
* care of by lBAD_CTCP
|
||||
*/
|
||||
DBprintf(("Aliased IP %lu and port %u\n", alias_address.s_addr, (unsigned)alias_port));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* An uninteresting CTCP - state entered right after '\001'
|
||||
* has been pushed. Also used to copy the rest of a DCC,
|
||||
* after IP address and port has been handled
|
||||
*/
|
||||
lBAD_CTCP:
|
||||
for (; i < dlen && iCopy < sizeof(newpacket); i++, iCopy++) {
|
||||
newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
|
||||
if (sptr[i] == '\001') {
|
||||
goto lNORMAL_TEXT;
|
||||
}
|
||||
}
|
||||
goto lPACKET_DONE;
|
||||
/* Normal text */
|
||||
lNORMAL_TEXT:
|
||||
for (; i < dlen && iCopy < sizeof(newpacket); i++, iCopy++) {
|
||||
newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
|
||||
if (sptr[i] == '\001') {
|
||||
goto lCTCP_START;
|
||||
}
|
||||
}
|
||||
/* Handle the end of a packet */
|
||||
lPACKET_DONE:
|
||||
iCopy = iCopy > maxsize - copyat ? maxsize - copyat : iCopy;
|
||||
memcpy(sptr + copyat, newpacket, iCopy);
|
||||
|
||||
/* Save information regarding modified seq and ack numbers */
|
||||
{
|
||||
int delta;
|
||||
|
||||
SetAckModified(lnk);
|
||||
delta = GetDeltaSeqOut(pip, lnk);
|
||||
AddSeq(pip, lnk, delta + copyat + iCopy - dlen);
|
||||
}
|
||||
|
||||
/* Revise IP header */
|
||||
{
|
||||
u_short new_len;
|
||||
|
||||
new_len = htons(hlen + iCopy + copyat);
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
&new_len,
|
||||
&pip->ip_len,
|
||||
1);
|
||||
pip->ip_len = new_len;
|
||||
}
|
||||
|
||||
/* Compute TCP checksum for revised packet */
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Notes:
|
||||
[Note 1]
|
||||
The initial search will most often fail; it could be replaced with a 32-bit specific search.
|
||||
Such a search would be done for 32-bit unsigned value V:
|
||||
V ^= 0x01010101; (Search is for null bytes)
|
||||
if( ((V-0x01010101)^V) & 0x80808080 ) {
|
||||
(found a null bytes which was a 01 byte)
|
||||
}
|
||||
To assert that the processor is 32-bits, do
|
||||
extern int ircdccar[32]; (32 bits)
|
||||
extern int ircdccar[CHAR_BIT*sizeof(unsigned int)];
|
||||
which will generate a type-error on all but 32-bit machines.
|
||||
|
||||
[Note 2] This routine really ought to be replaced with one that
|
||||
creates a transparent proxy on the aliasing host, to allow arbitary
|
||||
changes in the TCP stream. This should not be too difficult given
|
||||
this base; I (ee) will try to do this some time later.
|
||||
*/
|
@ -1,355 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Charles Mott <cm@linktel.net>
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Alias_local.h contains the function prototypes for alias.c,
|
||||
* alias_db.c, alias_util.c and alias_ftp.c, alias_irc.c (as well
|
||||
* as any future add-ons). It also includes macros, globals and
|
||||
* struct definitions shared by more than one alias*.c file.
|
||||
*
|
||||
* This include file is intended to be used only within the aliasing
|
||||
* software. Outside world interfaces are defined in alias.h
|
||||
*
|
||||
* This software is placed into the public domain with no restrictions
|
||||
* on its distribution.
|
||||
*
|
||||
* Initial version: August, 1996 (cjm)
|
||||
*
|
||||
* <updated several times by original author and Eivind Eklund>
|
||||
*/
|
||||
|
||||
#ifndef _ALIAS_LOCAL_H_
|
||||
#define _ALIAS_LOCAL_H_
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
/* Sizes of input and output link tables */
|
||||
#define LINK_TABLE_OUT_SIZE 101
|
||||
#define LINK_TABLE_IN_SIZE 4001
|
||||
|
||||
struct proxy_entry;
|
||||
|
||||
struct libalias {
|
||||
LIST_ENTRY(libalias) instancelist;
|
||||
|
||||
int packetAliasMode; /* Mode flags */
|
||||
/* - documented in alias.h */
|
||||
|
||||
struct in_addr aliasAddress; /* Address written onto source */
|
||||
/* field of IP packet. */
|
||||
|
||||
struct in_addr targetAddress; /* IP address incoming packets */
|
||||
/* are sent to if no aliasing */
|
||||
/* link already exists */
|
||||
|
||||
struct in_addr nullAddress; /* Used as a dummy parameter for */
|
||||
/* some function calls */
|
||||
|
||||
LIST_HEAD (, alias_link) linkTableOut[LINK_TABLE_OUT_SIZE];
|
||||
/* Lookup table of pointers to */
|
||||
/* chains of link records. Each */
|
||||
|
||||
LIST_HEAD (, alias_link) linkTableIn[LINK_TABLE_IN_SIZE];
|
||||
/* link record is doubly indexed */
|
||||
/* into input and output lookup */
|
||||
/* tables. */
|
||||
|
||||
/* Link statistics */
|
||||
int icmpLinkCount;
|
||||
int udpLinkCount;
|
||||
int tcpLinkCount;
|
||||
int pptpLinkCount;
|
||||
int protoLinkCount;
|
||||
int fragmentIdLinkCount;
|
||||
int fragmentPtrLinkCount;
|
||||
int sockCount;
|
||||
|
||||
int cleanupIndex; /* Index to chain of link table */
|
||||
/* being inspected for old links */
|
||||
|
||||
int timeStamp; /* System time in seconds for */
|
||||
/* current packet */
|
||||
|
||||
int lastCleanupTime; /* Last time
|
||||
* IncrementalCleanup() */
|
||||
/* was called */
|
||||
|
||||
int houseKeepingResidual; /* used by HouseKeeping() */
|
||||
|
||||
int deleteAllLinks; /* If equal to zero, DeleteLink() */
|
||||
/* will not remove permanent links */
|
||||
|
||||
FILE *monitorFile; /* File descriptor for link */
|
||||
/* statistics monitoring file */
|
||||
|
||||
int newDefaultLink; /* Indicates if a new aliasing */
|
||||
/* link has been created after a */
|
||||
/* call to PacketAliasIn/Out(). */
|
||||
|
||||
#ifndef NO_FW_PUNCH
|
||||
int fireWallFD; /* File descriptor to be able to */
|
||||
/* control firewall. Opened by */
|
||||
/* PacketAliasSetMode on first */
|
||||
/* setting the PKT_ALIAS_PUNCH_FW */
|
||||
/* flag. */
|
||||
int fireWallBaseNum; /* The first firewall entry
|
||||
* free for our use */
|
||||
int fireWallNumNums; /* How many entries can we
|
||||
* use? */
|
||||
int fireWallActiveNum; /* Which entry did we last
|
||||
* use? */
|
||||
char *fireWallField; /* bool array for entries */
|
||||
#endif
|
||||
|
||||
unsigned int skinnyPort; /* TCP port used by the Skinny */
|
||||
/* protocol. */
|
||||
|
||||
struct proxy_entry *proxyList;
|
||||
|
||||
struct in_addr true_addr; /* in network byte order. */
|
||||
u_short true_port; /* in host byte order. */
|
||||
|
||||
};
|
||||
|
||||
/* Macros */
|
||||
|
||||
/*
|
||||
* The following macro is used to update an
|
||||
* internet checksum. "delta" is a 32-bit
|
||||
* accumulation of all the changes to the
|
||||
* checksum (adding in new 16-bit words and
|
||||
* subtracting out old words), and "cksum"
|
||||
* is the checksum value to be updated.
|
||||
*/
|
||||
#define ADJUST_CHECKSUM(acc, cksum) \
|
||||
do { \
|
||||
acc += cksum; \
|
||||
if (acc < 0) { \
|
||||
acc = -acc; \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) ~acc; \
|
||||
} else { \
|
||||
acc = (acc >> 16) + (acc & 0xffff); \
|
||||
acc += acc >> 16; \
|
||||
cksum = (u_short) acc; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
/* General utilities */
|
||||
u_short IpChecksum(struct ip *_pip);
|
||||
u_short TcpChecksum(struct ip *_pip);
|
||||
void
|
||||
DifferentialChecksum(u_short * _cksum, void * _new, void * _old, int _n);
|
||||
|
||||
/* Internal data access */
|
||||
struct alias_link *
|
||||
FindIcmpIn(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
u_short _id_alias, int _create);
|
||||
struct alias_link *
|
||||
FindIcmpOut(struct libalias *la, struct in_addr _src_addr, struct in_addr _dst_addr,
|
||||
u_short _id, int _create);
|
||||
struct alias_link *
|
||||
FindFragmentIn1(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
u_short _ip_id);
|
||||
struct alias_link *
|
||||
FindFragmentIn2(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
u_short _ip_id);
|
||||
struct alias_link *
|
||||
AddFragmentPtrLink(struct libalias *la, struct in_addr _dst_addr, u_short _ip_id);
|
||||
struct alias_link *
|
||||
FindFragmentPtr(struct libalias *la, struct in_addr _dst_addr, u_short _ip_id);
|
||||
struct alias_link *
|
||||
FindProtoIn(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
u_char _proto);
|
||||
struct alias_link *
|
||||
FindProtoOut(struct libalias *la, struct in_addr _src_addr, struct in_addr _dst_addr,
|
||||
u_char _proto);
|
||||
struct alias_link *
|
||||
FindUdpTcpIn(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
u_short _dst_port, u_short _alias_port, u_char _proto, int _create);
|
||||
struct alias_link *
|
||||
FindUdpTcpOut(struct libalias *la, struct in_addr _src_addr, struct in_addr _dst_addr,
|
||||
u_short _src_port, u_short _dst_port, u_char _proto, int _create);
|
||||
struct alias_link *
|
||||
AddPptp(struct libalias *la, struct in_addr _src_addr, struct in_addr _dst_addr,
|
||||
struct in_addr _alias_addr, u_int16_t _src_call_id);
|
||||
struct alias_link *
|
||||
FindPptpOutByCallId(struct libalias *la, struct in_addr _src_addr,
|
||||
struct in_addr _dst_addr, u_int16_t _src_call_id);
|
||||
struct alias_link *
|
||||
FindPptpInByCallId(struct libalias *la, struct in_addr _dst_addr,
|
||||
struct in_addr _alias_addr, u_int16_t _dst_call_id);
|
||||
struct alias_link *
|
||||
FindPptpOutByPeerCallId(struct libalias *la, struct in_addr _src_addr,
|
||||
struct in_addr _dst_addr, u_int16_t _dst_call_id);
|
||||
struct alias_link *
|
||||
FindPptpInByPeerCallId(struct libalias *la, struct in_addr _dst_addr,
|
||||
struct in_addr _alias_addr, u_int16_t _alias_call_id);
|
||||
struct alias_link *
|
||||
FindRtspOut(struct libalias *la, struct in_addr _src_addr, struct in_addr _dst_addr,
|
||||
u_short _src_port, u_short _alias_port, u_char _proto);
|
||||
struct in_addr
|
||||
FindOriginalAddress(struct libalias *la, struct in_addr _alias_addr);
|
||||
struct in_addr
|
||||
FindAliasAddress(struct libalias *la, struct in_addr _original_addr);
|
||||
|
||||
/* External data access/modification */
|
||||
int
|
||||
FindNewPortGroup(struct libalias *la, 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);
|
||||
void GetFragmentAddr(struct alias_link *_lnk, struct in_addr *_src_addr);
|
||||
void SetFragmentAddr(struct alias_link *_lnk, struct in_addr _src_addr);
|
||||
void GetFragmentPtr(struct alias_link *_lnk, char **_fptr);
|
||||
void SetFragmentPtr(struct alias_link *_lnk, char *fptr);
|
||||
void SetStateIn(struct alias_link *_lnk, int _state);
|
||||
void SetStateOut(struct alias_link *_lnk, int _state);
|
||||
int GetStateIn (struct alias_link *_lnk);
|
||||
int GetStateOut(struct alias_link *_lnk);
|
||||
struct in_addr
|
||||
GetOriginalAddress(struct alias_link *_lnk);
|
||||
struct in_addr
|
||||
GetDestAddress(struct alias_link *_lnk);
|
||||
struct in_addr
|
||||
GetAliasAddress(struct alias_link *_lnk);
|
||||
struct in_addr
|
||||
GetDefaultAliasAddress(struct libalias *la);
|
||||
void SetDefaultAliasAddress(struct libalias *la, struct in_addr _alias_addr);
|
||||
u_short GetOriginalPort(struct alias_link *_lnk);
|
||||
u_short GetAliasPort(struct alias_link *_lnk);
|
||||
struct in_addr
|
||||
GetProxyAddress(struct alias_link *_lnk);
|
||||
void SetProxyAddress(struct alias_link *_lnk, struct in_addr _addr);
|
||||
u_short GetProxyPort(struct alias_link *_lnk);
|
||||
void SetProxyPort(struct alias_link *_lnk, u_short _port);
|
||||
void SetAckModified(struct alias_link *_lnk);
|
||||
int GetAckModified(struct alias_link *_lnk);
|
||||
int GetDeltaAckIn(struct ip *_pip, struct alias_link *_lnk);
|
||||
int GetDeltaSeqOut(struct ip *_pip, struct alias_link *_lnk);
|
||||
void AddSeq (struct ip *_pip, struct alias_link *_lnk, int _delta);
|
||||
void SetExpire (struct alias_link *_lnk, int _expire);
|
||||
void ClearCheckNewLink(struct libalias *la);
|
||||
void SetProtocolFlags(struct alias_link *_lnk, int _pflags);
|
||||
int GetProtocolFlags(struct alias_link *_lnk);
|
||||
void SetDestCallId(struct alias_link *_lnk, u_int16_t _cid);
|
||||
|
||||
#ifndef NO_FW_PUNCH
|
||||
void PunchFWHole(struct alias_link *_lnk);
|
||||
|
||||
#endif
|
||||
|
||||
/* Housekeeping function */
|
||||
void HouseKeeping(struct libalias *);
|
||||
|
||||
/* Tcp specfic routines */
|
||||
/* lint -save -library Suppress flexelint warnings */
|
||||
|
||||
/* FTP routines */
|
||||
void
|
||||
AliasHandleFtpOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
|
||||
int _maxpacketsize);
|
||||
|
||||
/* IRC routines */
|
||||
void
|
||||
AliasHandleIrcOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
|
||||
int _maxsize);
|
||||
|
||||
/* RTSP routines */
|
||||
void
|
||||
AliasHandleRtspOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
|
||||
int _maxpacketsize);
|
||||
|
||||
/* PPTP routines */
|
||||
void AliasHandlePptpOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk);
|
||||
void AliasHandlePptpIn(struct libalias *la, struct ip *_pip, struct alias_link *_lnk);
|
||||
int AliasHandlePptpGreOut(struct libalias *la, struct ip *_pip);
|
||||
int AliasHandlePptpGreIn(struct libalias *la, struct ip *_pip);
|
||||
|
||||
/* NetBIOS routines */
|
||||
int
|
||||
AliasHandleUdpNbt(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
|
||||
struct in_addr *_alias_address, u_short _alias_port);
|
||||
int
|
||||
AliasHandleUdpNbtNS(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
|
||||
struct in_addr *_alias_address, u_short * _alias_port,
|
||||
struct in_addr *_original_address, u_short * _original_port);
|
||||
|
||||
/* CUSeeMe routines */
|
||||
void AliasHandleCUSeeMeOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk);
|
||||
void AliasHandleCUSeeMeIn(struct libalias *la, struct ip *_pip, struct in_addr _original_addr);
|
||||
|
||||
/* Skinny routines */
|
||||
void AliasHandleSkinny(struct libalias *la, struct ip *_pip, struct alias_link *_lnk);
|
||||
|
||||
/* Transparent proxy routines */
|
||||
int
|
||||
ProxyCheck(struct libalias *la, struct ip *_pip, struct in_addr *_proxy_server_addr,
|
||||
u_short * _proxy_server_port);
|
||||
void
|
||||
ProxyModify(struct libalias *la, struct alias_link *_lnk, struct ip *_pip,
|
||||
int _maxpacketsize, int _proxy_type);
|
||||
|
||||
enum alias_tcp_state {
|
||||
ALIAS_TCP_STATE_NOT_CONNECTED,
|
||||
ALIAS_TCP_STATE_CONNECTED,
|
||||
ALIAS_TCP_STATE_DISCONNECTED
|
||||
};
|
||||
|
||||
#if defined(_NETINET_IP_H_)
|
||||
static __inline void *
|
||||
ip_next(struct ip *iphdr)
|
||||
{
|
||||
char *p = (char *)iphdr;
|
||||
return (&p[iphdr->ip_hl * 4]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_NETINET_TCP_H_)
|
||||
static __inline void *
|
||||
tcp_next(struct tcphdr *tcphdr)
|
||||
{
|
||||
char *p = (char *)tcphdr;
|
||||
return (&p[tcphdr->th_off * 4]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_NETINET_UDP_H_)
|
||||
static __inline void *
|
||||
udp_next(struct udphdr *udphdr)
|
||||
{
|
||||
return ((void *)(udphdr + 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*lint -restore */
|
||||
|
||||
#endif /* !_ALIAS_LOCAL_H_ */
|
@ -1,722 +0,0 @@
|
||||
/*-
|
||||
* Written by Atsushi Murai <amurai@spec.co.jp>
|
||||
* Copyright (c) 1998, System Planning and Engineering Co.
|
||||
* 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.
|
||||
* TODO:
|
||||
* oClean up.
|
||||
* oConsidering for word alignment for other platform.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
alias_nbt.c performs special processing for NetBios over TCP/IP
|
||||
sessions by UDP.
|
||||
|
||||
Initial version: May, 1998 (Atsushi Murai <amurai@spec.co.jp>)
|
||||
|
||||
See HISTORY file for record of revisions.
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
typedef struct {
|
||||
struct in_addr oldaddr;
|
||||
u_short oldport;
|
||||
struct in_addr newaddr;
|
||||
u_short newport;
|
||||
u_short *uh_sum;
|
||||
} NBTArguments;
|
||||
|
||||
typedef struct {
|
||||
unsigned char type;
|
||||
unsigned char flags;
|
||||
u_short id;
|
||||
struct in_addr source_ip;
|
||||
u_short source_port;
|
||||
u_short len;
|
||||
u_short offset;
|
||||
} NbtDataHeader;
|
||||
|
||||
#define OpQuery 0
|
||||
#define OpUnknown 4
|
||||
#define OpRegist 5
|
||||
#define OpRelease 6
|
||||
#define OpWACK 7
|
||||
#define OpRefresh 8
|
||||
typedef struct {
|
||||
u_short nametrid;
|
||||
u_short dir: 1, opcode:4, nmflags:7, rcode:4;
|
||||
u_short qdcount;
|
||||
u_short ancount;
|
||||
u_short nscount;
|
||||
u_short arcount;
|
||||
} NbtNSHeader;
|
||||
|
||||
#define FMT_ERR 0x1
|
||||
#define SRV_ERR 0x2
|
||||
#define IMP_ERR 0x4
|
||||
#define RFS_ERR 0x5
|
||||
#define ACT_ERR 0x6
|
||||
#define CFT_ERR 0x7
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
PrintRcode(u_char rcode)
|
||||
{
|
||||
|
||||
switch (rcode) {
|
||||
case FMT_ERR:
|
||||
printf("\nFormat Error.");
|
||||
case SRV_ERR:
|
||||
printf("\nSever failure.");
|
||||
case IMP_ERR:
|
||||
printf("\nUnsupported request error.\n");
|
||||
case RFS_ERR:
|
||||
printf("\nRefused error.\n");
|
||||
case ACT_ERR:
|
||||
printf("\nActive error.\n");
|
||||
case CFT_ERR:
|
||||
printf("\nName in conflict error.\n");
|
||||
default:
|
||||
printf("\n?%c?=%0x\n", '?', rcode);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Handling Name field */
|
||||
static u_char *
|
||||
AliasHandleName(u_char * p, char *pmax)
|
||||
{
|
||||
|
||||
u_char *s;
|
||||
u_char c;
|
||||
int compress;
|
||||
|
||||
/* Following length field */
|
||||
|
||||
if (p == NULL || (char *)p >= pmax)
|
||||
return (NULL);
|
||||
|
||||
if (*p & 0xc0) {
|
||||
p = p + 2;
|
||||
if ((char *)p > pmax)
|
||||
return (NULL);
|
||||
return ((u_char *) p);
|
||||
}
|
||||
while ((*p & 0x3f) != 0x00) {
|
||||
s = p + 1;
|
||||
if (*p == 0x20)
|
||||
compress = 1;
|
||||
else
|
||||
compress = 0;
|
||||
|
||||
/* Get next length field */
|
||||
p = (u_char *) (p + (*p & 0x3f) + 1);
|
||||
if ((char *)p > pmax) {
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(":");
|
||||
#endif
|
||||
while (s < p) {
|
||||
if (compress == 1) {
|
||||
c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11));
|
||||
#ifdef DEBUG
|
||||
if (isprint(c))
|
||||
printf("%c", c);
|
||||
else
|
||||
printf("<0x%02x>", c);
|
||||
#endif
|
||||
s += 2;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printf("%c", *s);
|
||||
#endif
|
||||
s++;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(":");
|
||||
#endif
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* Set up to out of Name field */
|
||||
if (p == NULL || (char *)p >= pmax)
|
||||
p = NULL;
|
||||
else
|
||||
p++;
|
||||
return ((u_char *) p);
|
||||
}
|
||||
|
||||
/*
|
||||
* NetBios Datagram Handler (IP/UDP)
|
||||
*/
|
||||
#define DGM_DIRECT_UNIQ 0x10
|
||||
#define DGM_DIRECT_GROUP 0x11
|
||||
#define DGM_BROADCAST 0x12
|
||||
#define DGM_ERROR 0x13
|
||||
#define DGM_QUERY 0x14
|
||||
#define DGM_POSITIVE_RES 0x15
|
||||
#define DGM_NEGATIVE_RES 0x16
|
||||
|
||||
int
|
||||
AliasHandleUdpNbt(
|
||||
struct libalias *la,
|
||||
struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *lnk,
|
||||
struct in_addr *alias_address,
|
||||
u_short alias_port
|
||||
)
|
||||
{
|
||||
struct udphdr *uh;
|
||||
NbtDataHeader *ndh;
|
||||
u_char *p = NULL;
|
||||
char *pmax;
|
||||
|
||||
(void)la;
|
||||
(void)lnk;
|
||||
|
||||
/* Calculate data length of UDP packet */
|
||||
uh = (struct udphdr *)ip_next(pip);
|
||||
pmax = (char *)uh + ntohs(uh->uh_ulen);
|
||||
|
||||
ndh = (NbtDataHeader *)udp_next(uh);
|
||||
if ((char *)(ndh + 1) > pmax)
|
||||
return (-1);
|
||||
#ifdef DEBUG
|
||||
printf("\nType=%02x,", ndh->type);
|
||||
#endif
|
||||
switch (ndh->type) {
|
||||
case DGM_DIRECT_UNIQ:
|
||||
case DGM_DIRECT_GROUP:
|
||||
case DGM_BROADCAST:
|
||||
p = (u_char *) ndh + 14;
|
||||
p = AliasHandleName(p, pmax); /* Source Name */
|
||||
p = AliasHandleName(p, pmax); /* Destination Name */
|
||||
break;
|
||||
case DGM_ERROR:
|
||||
p = (u_char *) ndh + 11;
|
||||
break;
|
||||
case DGM_QUERY:
|
||||
case DGM_POSITIVE_RES:
|
||||
case DGM_NEGATIVE_RES:
|
||||
p = (u_char *) ndh + 10;
|
||||
p = AliasHandleName(p, pmax); /* Destination Name */
|
||||
break;
|
||||
}
|
||||
if (p == NULL || (char *)p > pmax)
|
||||
p = NULL;
|
||||
#ifdef DEBUG
|
||||
printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
|
||||
#endif
|
||||
/* Doing an IP address and Port number Translation */
|
||||
if (uh->uh_sum != 0) {
|
||||
int acc;
|
||||
u_short *sptr;
|
||||
|
||||
acc = ndh->source_port;
|
||||
acc -= alias_port;
|
||||
sptr = (u_short *) & (ndh->source_ip);
|
||||
acc += *sptr++;
|
||||
acc += *sptr;
|
||||
sptr = (u_short *) alias_address;
|
||||
acc -= *sptr++;
|
||||
acc -= *sptr;
|
||||
ADJUST_CHECKSUM(acc, uh->uh_sum);
|
||||
}
|
||||
ndh->source_ip = *alias_address;
|
||||
ndh->source_port = alias_port;
|
||||
#ifdef DEBUG
|
||||
printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
|
||||
fflush(stdout);
|
||||
#endif
|
||||
return ((p == NULL) ? -1 : 0);
|
||||
}
|
||||
|
||||
/* Question Section */
|
||||
#define QS_TYPE_NB 0x0020
|
||||
#define QS_TYPE_NBSTAT 0x0021
|
||||
#define QS_CLAS_IN 0x0001
|
||||
typedef struct {
|
||||
u_short type; /* The type of Request */
|
||||
u_short class; /* The class of Request */
|
||||
} NBTNsQuestion;
|
||||
|
||||
static u_char *
|
||||
AliasHandleQuestion(
|
||||
u_short count,
|
||||
NBTNsQuestion * q,
|
||||
char *pmax,
|
||||
NBTArguments * nbtarg)
|
||||
{
|
||||
|
||||
(void)nbtarg;
|
||||
|
||||
while (count != 0) {
|
||||
/* Name Filed */
|
||||
q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax);
|
||||
|
||||
if (q == NULL || (char *)(q + 1) > pmax) {
|
||||
q = NULL;
|
||||
break;
|
||||
}
|
||||
/* Type and Class filed */
|
||||
switch (ntohs(q->type)) {
|
||||
case QS_TYPE_NB:
|
||||
case QS_TYPE_NBSTAT:
|
||||
q = q + 1;
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
|
||||
/* Set up to out of Question Section */
|
||||
return ((u_char *) q);
|
||||
}
|
||||
|
||||
/* Resource Record */
|
||||
#define RR_TYPE_A 0x0001
|
||||
#define RR_TYPE_NS 0x0002
|
||||
#define RR_TYPE_NULL 0x000a
|
||||
#define RR_TYPE_NB 0x0020
|
||||
#define RR_TYPE_NBSTAT 0x0021
|
||||
#define RR_CLAS_IN 0x0001
|
||||
#define SizeOfNsResource 8
|
||||
typedef struct {
|
||||
u_short type;
|
||||
u_short class;
|
||||
unsigned int ttl;
|
||||
u_short rdlen;
|
||||
} NBTNsResource;
|
||||
|
||||
#define SizeOfNsRNB 6
|
||||
typedef struct {
|
||||
u_short g: 1 , ont:2, resv:13;
|
||||
struct in_addr addr;
|
||||
} NBTNsRNB;
|
||||
|
||||
static u_char *
|
||||
AliasHandleResourceNB(
|
||||
NBTNsResource * q,
|
||||
char *pmax,
|
||||
NBTArguments * nbtarg)
|
||||
{
|
||||
NBTNsRNB *nb;
|
||||
u_short bcount;
|
||||
|
||||
if (q == NULL || (char *)(q + 1) > pmax)
|
||||
return (NULL);
|
||||
/* Check out a length */
|
||||
bcount = ntohs(q->rdlen);
|
||||
|
||||
/* Forward to Resource NB position */
|
||||
nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource);
|
||||
|
||||
/* Processing all in_addr array */
|
||||
#ifdef DEBUG
|
||||
printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
|
||||
printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount);
|
||||
#endif
|
||||
while (nb != NULL && bcount != 0) {
|
||||
if ((char *)(nb + 1) > pmax) {
|
||||
nb = NULL;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("<%s>", inet_ntoa(nb->addr));
|
||||
#endif
|
||||
if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
|
||||
if (*nbtarg->uh_sum != 0) {
|
||||
int acc;
|
||||
u_short *sptr;
|
||||
|
||||
sptr = (u_short *) & (nb->addr);
|
||||
acc = *sptr++;
|
||||
acc += *sptr;
|
||||
sptr = (u_short *) & (nbtarg->newaddr);
|
||||
acc -= *sptr++;
|
||||
acc -= *sptr;
|
||||
ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
|
||||
}
|
||||
nb->addr = nbtarg->newaddr;
|
||||
#ifdef DEBUG
|
||||
printf("O");
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
printf(".");
|
||||
}
|
||||
#endif
|
||||
nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB);
|
||||
bcount -= SizeOfNsRNB;
|
||||
}
|
||||
if (nb == NULL || (char *)(nb + 1) > pmax) {
|
||||
nb = NULL;
|
||||
}
|
||||
return ((u_char *) nb);
|
||||
}
|
||||
|
||||
#define SizeOfResourceA 6
|
||||
typedef struct {
|
||||
struct in_addr addr;
|
||||
} NBTNsResourceA;
|
||||
|
||||
static u_char *
|
||||
AliasHandleResourceA(
|
||||
NBTNsResource * q,
|
||||
char *pmax,
|
||||
NBTArguments * nbtarg)
|
||||
{
|
||||
NBTNsResourceA *a;
|
||||
u_short bcount;
|
||||
|
||||
if (q == NULL || (char *)(q + 1) > pmax)
|
||||
return (NULL);
|
||||
|
||||
/* Forward to Resource A position */
|
||||
a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource));
|
||||
|
||||
/* Check out of length */
|
||||
bcount = ntohs(q->rdlen);
|
||||
|
||||
/* Processing all in_addr array */
|
||||
#ifdef DEBUG
|
||||
printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
|
||||
printf("->%s]", inet_ntoa(nbtarg->newaddr));
|
||||
#endif
|
||||
while (bcount != 0) {
|
||||
if (a == NULL || (char *)(a + 1) > pmax)
|
||||
return (NULL);
|
||||
#ifdef DEBUG
|
||||
printf("..%s", inet_ntoa(a->addr));
|
||||
#endif
|
||||
if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
|
||||
if (*nbtarg->uh_sum != 0) {
|
||||
int acc;
|
||||
u_short *sptr;
|
||||
|
||||
sptr = (u_short *) & (a->addr); /* Old */
|
||||
acc = *sptr++;
|
||||
acc += *sptr;
|
||||
sptr = (u_short *) & nbtarg->newaddr; /* New */
|
||||
acc -= *sptr++;
|
||||
acc -= *sptr;
|
||||
ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
|
||||
}
|
||||
a->addr = nbtarg->newaddr;
|
||||
}
|
||||
a++; /* XXXX */
|
||||
bcount -= SizeOfResourceA;
|
||||
}
|
||||
if (a == NULL || (char *)(a + 1) > pmax)
|
||||
a = NULL;
|
||||
return ((u_char *) a);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
u_short opcode:4, flags:8, resv:4;
|
||||
} NBTNsResourceNULL;
|
||||
|
||||
static u_char *
|
||||
AliasHandleResourceNULL(
|
||||
NBTNsResource * q,
|
||||
char *pmax,
|
||||
NBTArguments * nbtarg)
|
||||
{
|
||||
NBTNsResourceNULL *n;
|
||||
u_short bcount;
|
||||
|
||||
(void)nbtarg;
|
||||
|
||||
if (q == NULL || (char *)(q + 1) > pmax)
|
||||
return (NULL);
|
||||
|
||||
/* Forward to Resource NULL position */
|
||||
n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
|
||||
|
||||
/* Check out of length */
|
||||
bcount = ntohs(q->rdlen);
|
||||
|
||||
/* Processing all in_addr array */
|
||||
while (bcount != 0) {
|
||||
if ((char *)(n + 1) > pmax) {
|
||||
n = NULL;
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
bcount -= sizeof(NBTNsResourceNULL);
|
||||
}
|
||||
if ((char *)(n + 1) > pmax)
|
||||
n = NULL;
|
||||
|
||||
return ((u_char *) n);
|
||||
}
|
||||
|
||||
static u_char *
|
||||
AliasHandleResourceNS(
|
||||
NBTNsResource * q,
|
||||
char *pmax,
|
||||
NBTArguments * nbtarg)
|
||||
{
|
||||
NBTNsResourceNULL *n;
|
||||
u_short bcount;
|
||||
|
||||
(void)nbtarg;
|
||||
|
||||
if (q == NULL || (char *)(q + 1) > pmax)
|
||||
return (NULL);
|
||||
|
||||
/* Forward to Resource NULL position */
|
||||
n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
|
||||
|
||||
/* Check out of length */
|
||||
bcount = ntohs(q->rdlen);
|
||||
|
||||
/* Resource Record Name Filed */
|
||||
q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */
|
||||
|
||||
if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
|
||||
return (NULL);
|
||||
else
|
||||
return ((u_char *) n + bcount);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
u_short numnames;
|
||||
} NBTNsResourceNBSTAT;
|
||||
|
||||
static u_char *
|
||||
AliasHandleResourceNBSTAT(
|
||||
NBTNsResource * q,
|
||||
char *pmax,
|
||||
NBTArguments * nbtarg)
|
||||
{
|
||||
NBTNsResourceNBSTAT *n;
|
||||
u_short bcount;
|
||||
|
||||
(void)nbtarg;
|
||||
|
||||
if (q == NULL || (char *)(q + 1) > pmax)
|
||||
return (NULL);
|
||||
|
||||
/* Forward to Resource NBSTAT position */
|
||||
n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource));
|
||||
|
||||
/* Check out of length */
|
||||
bcount = ntohs(q->rdlen);
|
||||
|
||||
if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
|
||||
return (NULL);
|
||||
else
|
||||
return ((u_char *) n + bcount);
|
||||
}
|
||||
|
||||
static u_char *
|
||||
AliasHandleResource(
|
||||
u_short count,
|
||||
NBTNsResource * q,
|
||||
char *pmax,
|
||||
NBTArguments
|
||||
* nbtarg)
|
||||
{
|
||||
while (count != 0) {
|
||||
/* Resource Record Name Filed */
|
||||
q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax);
|
||||
|
||||
if (q == NULL || (char *)(q + 1) > pmax)
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
printf("type=%02x, count=%d\n", ntohs(q->type), count);
|
||||
#endif
|
||||
|
||||
/* Type and Class filed */
|
||||
switch (ntohs(q->type)) {
|
||||
case RR_TYPE_NB:
|
||||
q = (NBTNsResource *) AliasHandleResourceNB(
|
||||
q,
|
||||
pmax,
|
||||
nbtarg
|
||||
);
|
||||
break;
|
||||
case RR_TYPE_A:
|
||||
q = (NBTNsResource *) AliasHandleResourceA(
|
||||
q,
|
||||
pmax,
|
||||
nbtarg
|
||||
);
|
||||
break;
|
||||
case RR_TYPE_NS:
|
||||
q = (NBTNsResource *) AliasHandleResourceNS(
|
||||
q,
|
||||
pmax,
|
||||
nbtarg
|
||||
);
|
||||
break;
|
||||
case RR_TYPE_NULL:
|
||||
q = (NBTNsResource *) AliasHandleResourceNULL(
|
||||
q,
|
||||
pmax,
|
||||
nbtarg
|
||||
);
|
||||
break;
|
||||
case RR_TYPE_NBSTAT:
|
||||
q = (NBTNsResource *) AliasHandleResourceNBSTAT(
|
||||
q,
|
||||
pmax,
|
||||
nbtarg
|
||||
);
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf(
|
||||
"\nUnknown Type of Resource %0x\n",
|
||||
ntohs(q->type)
|
||||
);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
fflush(stdout);
|
||||
return ((u_char *) q);
|
||||
}
|
||||
|
||||
int
|
||||
AliasHandleUdpNbtNS(
|
||||
struct libalias *la,
|
||||
struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *lnk,
|
||||
struct in_addr *alias_address,
|
||||
u_short * alias_port,
|
||||
struct in_addr *original_address,
|
||||
u_short * original_port)
|
||||
{
|
||||
struct udphdr *uh;
|
||||
NbtNSHeader *nsh;
|
||||
u_char *p;
|
||||
char *pmax;
|
||||
NBTArguments nbtarg;
|
||||
|
||||
(void)la;
|
||||
(void)lnk;
|
||||
|
||||
/* Set up Common Parameter */
|
||||
nbtarg.oldaddr = *alias_address;
|
||||
nbtarg.oldport = *alias_port;
|
||||
nbtarg.newaddr = *original_address;
|
||||
nbtarg.newport = *original_port;
|
||||
|
||||
/* Calculate data length of UDP packet */
|
||||
uh = (struct udphdr *)ip_next(pip);
|
||||
nbtarg.uh_sum = &(uh->uh_sum);
|
||||
nsh = (NbtNSHeader *)udp_next(uh);
|
||||
p = (u_char *) (nsh + 1);
|
||||
pmax = (char *)uh + ntohs(uh->uh_ulen);
|
||||
|
||||
if ((char *)(nsh + 1) > pmax)
|
||||
return (-1);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
|
||||
", an=%04x, ns=%04x, ar=%04x, [%d]-->",
|
||||
nsh->dir ? "Response" : "Request",
|
||||
nsh->nametrid,
|
||||
nsh->opcode,
|
||||
nsh->nmflags,
|
||||
nsh->rcode,
|
||||
ntohs(nsh->qdcount),
|
||||
ntohs(nsh->ancount),
|
||||
ntohs(nsh->nscount),
|
||||
ntohs(nsh->arcount),
|
||||
(u_char *) p - (u_char *) nsh
|
||||
);
|
||||
#endif
|
||||
|
||||
/* Question Entries */
|
||||
if (ntohs(nsh->qdcount) != 0) {
|
||||
p = AliasHandleQuestion(
|
||||
ntohs(nsh->qdcount),
|
||||
(NBTNsQuestion *) p,
|
||||
pmax,
|
||||
&nbtarg
|
||||
);
|
||||
}
|
||||
/* Answer Resource Records */
|
||||
if (ntohs(nsh->ancount) != 0) {
|
||||
p = AliasHandleResource(
|
||||
ntohs(nsh->ancount),
|
||||
(NBTNsResource *) p,
|
||||
pmax,
|
||||
&nbtarg
|
||||
);
|
||||
}
|
||||
/* Authority Resource Recodrs */
|
||||
if (ntohs(nsh->nscount) != 0) {
|
||||
p = AliasHandleResource(
|
||||
ntohs(nsh->nscount),
|
||||
(NBTNsResource *) p,
|
||||
pmax,
|
||||
&nbtarg
|
||||
);
|
||||
}
|
||||
/* Additional Resource Recodrs */
|
||||
if (ntohs(nsh->arcount) != 0) {
|
||||
p = AliasHandleResource(
|
||||
ntohs(nsh->arcount),
|
||||
(NBTNsResource *) p,
|
||||
pmax,
|
||||
&nbtarg
|
||||
);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
PrintRcode(nsh->rcode);
|
||||
#endif
|
||||
return ((p == NULL) ? -1 : 0);
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Poul-Henning Kamp <phk@FreeBSD.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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include "alias.h"
|
||||
|
||||
/*
|
||||
* These functions are for backwards compatibility and because apps may
|
||||
* be linked against shlib versions, they have to be actual functions,
|
||||
* we cannot inline them.
|
||||
*/
|
||||
|
||||
static struct libalias *la;
|
||||
|
||||
void
|
||||
PacketAliasInit(void)
|
||||
{
|
||||
|
||||
la = LibAliasInit(la);
|
||||
}
|
||||
|
||||
void
|
||||
PacketAliasSetAddress(struct in_addr _addr)
|
||||
{
|
||||
|
||||
LibAliasSetAddress(la, _addr);
|
||||
}
|
||||
|
||||
void
|
||||
PacketAliasSetFWBase(unsigned int _base, unsigned int _num)
|
||||
{
|
||||
|
||||
LibAliasSetFWBase(la, _base, _num);
|
||||
}
|
||||
|
||||
void
|
||||
PacketAliasSetSkinnyPort(unsigned int _port)
|
||||
{
|
||||
|
||||
LibAliasSetSkinnyPort(la, _port);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PacketAliasSetMode(unsigned int _flags, unsigned int _mask)
|
||||
{
|
||||
|
||||
return LibAliasSetMode(la, _flags, _mask);
|
||||
}
|
||||
|
||||
void
|
||||
PacketAliasUninit(void)
|
||||
{
|
||||
|
||||
LibAliasUninit(la);
|
||||
la = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
PacketAliasIn(char *_ptr, int _maxpacketsize)
|
||||
{
|
||||
return LibAliasIn(la, _ptr, _maxpacketsize);
|
||||
}
|
||||
|
||||
int
|
||||
PacketAliasOut(char *_ptr, int _maxpacketsize)
|
||||
{
|
||||
|
||||
return LibAliasOut(la, _ptr, _maxpacketsize);
|
||||
}
|
||||
|
||||
int
|
||||
PacketUnaliasOut(char *_ptr, int _maxpacketsize)
|
||||
{
|
||||
|
||||
return LibAliasUnaliasOut(la, _ptr, _maxpacketsize);
|
||||
}
|
||||
|
||||
int
|
||||
PacketAliasAddServer(struct alias_link *_lnk,
|
||||
struct in_addr _addr, unsigned short _port)
|
||||
{
|
||||
|
||||
return LibAliasAddServer(la, _lnk, _addr, _port);
|
||||
}
|
||||
|
||||
struct alias_link *
|
||||
PacketAliasRedirectAddr(struct in_addr _src_addr,
|
||||
struct in_addr _alias_addr)
|
||||
{
|
||||
|
||||
return LibAliasRedirectAddr(la, _src_addr, _alias_addr);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PacketAliasRedirectDynamic(struct alias_link *_lnk)
|
||||
{
|
||||
|
||||
return LibAliasRedirectDynamic(la, _lnk);
|
||||
}
|
||||
|
||||
void
|
||||
PacketAliasRedirectDelete(struct alias_link *_lnk)
|
||||
{
|
||||
|
||||
LibAliasRedirectDelete(la, _lnk);
|
||||
}
|
||||
|
||||
struct alias_link *
|
||||
PacketAliasRedirectPort(struct in_addr _src_addr,
|
||||
unsigned short _src_port, struct in_addr _dst_addr,
|
||||
unsigned short _dst_port, struct in_addr _alias_addr,
|
||||
unsigned short _alias_port, unsigned char _proto)
|
||||
{
|
||||
|
||||
return LibAliasRedirectPort(la, _src_addr, _src_port, _dst_addr,
|
||||
_dst_port, _alias_addr, _alias_port, _proto);
|
||||
}
|
||||
|
||||
struct alias_link *
|
||||
PacketAliasRedirectProto(struct in_addr _src_addr,
|
||||
struct in_addr _dst_addr, struct in_addr _alias_addr,
|
||||
unsigned char _proto)
|
||||
{
|
||||
|
||||
return LibAliasRedirectProto(la, _src_addr, _dst_addr, _alias_addr,
|
||||
_proto);
|
||||
}
|
||||
|
||||
void
|
||||
PacketAliasFragmentIn(char *_ptr, char *_ptr_fragment)
|
||||
{
|
||||
|
||||
LibAliasFragmentIn(la, _ptr, _ptr_fragment);
|
||||
}
|
||||
|
||||
char *
|
||||
PacketAliasGetFragment(char *_ptr)
|
||||
{
|
||||
|
||||
return LibAliasGetFragment(la, _ptr);
|
||||
}
|
||||
|
||||
int
|
||||
PacketAliasSaveFragment(char *_ptr)
|
||||
{
|
||||
return LibAliasSaveFragment(la, _ptr);
|
||||
}
|
||||
|
||||
int
|
||||
PacketAliasCheckNewLink(void)
|
||||
{
|
||||
|
||||
return LibAliasCheckNewLink(la);
|
||||
}
|
||||
|
||||
unsigned short
|
||||
PacketAliasInternetChecksum(unsigned short *_ptr, int _nbytes)
|
||||
{
|
||||
|
||||
return LibAliasInternetChecksum(la, _ptr, _nbytes);
|
||||
}
|
||||
|
||||
void
|
||||
PacketAliasSetTarget(struct in_addr _target_addr)
|
||||
{
|
||||
|
||||
LibAliasSetTarget(la, _target_addr);
|
||||
}
|
||||
|
||||
/* Transparent proxying routines. */
|
||||
int
|
||||
PacketAliasProxyRule(const char *_cmd)
|
||||
{
|
||||
|
||||
return LibAliasProxyRule(la, _cmd);
|
||||
}
|
@ -1,373 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$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 PPTP alias link is created.
|
||||
The PPTP 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 <sys/types.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
/*
|
||||
* PPTP definitions
|
||||
*/
|
||||
|
||||
struct grehdr { /* Enhanced GRE header. */
|
||||
u_int16_t gh_flags; /* Flags. */
|
||||
u_int16_t gh_protocol; /* Protocol type. */
|
||||
u_int16_t gh_length; /* Payload length. */
|
||||
u_int16_t gh_call_id; /* Call ID. */
|
||||
u_int32_t gh_seq_no; /* Sequence number (optional). */
|
||||
u_int32_t gh_ack_no; /* Acknowledgment number
|
||||
* (optional). */
|
||||
};
|
||||
typedef struct grehdr GreHdr;
|
||||
|
||||
/* 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_EchoReply = 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 pptpCodes {
|
||||
u_int8_t resCode;/* Result Code */
|
||||
u_int8_t errCode;/* Error Code */
|
||||
};
|
||||
typedef struct pptpCodes *PptpCode;
|
||||
|
||||
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 *);
|
||||
|
||||
|
||||
void
|
||||
AliasHandlePptpOut(struct libalias *la,
|
||||
struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *lnk)
|
||||
{ /* The PPTP control link */
|
||||
struct alias_link *pptp_lnk;
|
||||
PptpCallId cptr;
|
||||
PptpCode codes;
|
||||
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_OutCallRequest:
|
||||
case PPTP_OutCallReply:
|
||||
case PPTP_InCallRequest:
|
||||
case PPTP_InCallReply:
|
||||
/*
|
||||
* Establish PPTP link for address and Call ID found in
|
||||
* control message.
|
||||
*/
|
||||
pptp_lnk = AddPptp(la, GetOriginalAddress(lnk), GetDestAddress(lnk),
|
||||
GetAliasAddress(lnk), cptr->cid1);
|
||||
break;
|
||||
case PPTP_CallClearRequest:
|
||||
case PPTP_CallDiscNotify:
|
||||
/*
|
||||
* Find PPTP link for address and Call ID found in control
|
||||
* message.
|
||||
*/
|
||||
pptp_lnk = FindPptpOutByCallId(la, GetOriginalAddress(lnk),
|
||||
GetDestAddress(lnk),
|
||||
cptr->cid1);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (pptp_lnk != NULL) {
|
||||
int accumulate = cptr->cid1;
|
||||
|
||||
/* alias the Call Id */
|
||||
cptr->cid1 = GetAliasPort(pptp_lnk);
|
||||
|
||||
/* Compute TCP checksum for revised packet */
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
accumulate -= cptr->cid1;
|
||||
ADJUST_CHECKSUM(accumulate, tc->th_sum);
|
||||
|
||||
switch (ctl_type) {
|
||||
case PPTP_OutCallReply:
|
||||
case PPTP_InCallReply:
|
||||
codes = (PptpCode) (cptr + 1);
|
||||
if (codes->resCode == 1) /* Connection
|
||||
* established, */
|
||||
SetDestCallId(pptp_lnk, /* note the Peer's Call
|
||||
* ID. */
|
||||
cptr->cid2);
|
||||
else
|
||||
SetExpire(pptp_lnk, 0); /* Connection refused. */
|
||||
break;
|
||||
case PPTP_CallDiscNotify: /* Connection closed. */
|
||||
SetExpire(pptp_lnk, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AliasHandlePptpIn(struct libalias *la,
|
||||
struct ip *pip, /* IP packet to examine/patch */
|
||||
struct alias_link *lnk)
|
||||
{ /* The PPTP control link */
|
||||
struct alias_link *pptp_lnk;
|
||||
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;
|
||||
case PPTP_CallDiscNotify: /* Connection closed. */
|
||||
pptp_lnk = FindPptpInByCallId(la, GetDestAddress(lnk),
|
||||
GetAliasAddress(lnk),
|
||||
cptr->cid1);
|
||||
if (pptp_lnk != NULL)
|
||||
SetExpire(pptp_lnk, 0);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find PPTP link for address and Call ID found in PPTP Control Msg */
|
||||
pptp_lnk = FindPptpInByPeerCallId(la, GetDestAddress(lnk),
|
||||
GetAliasAddress(lnk),
|
||||
*pcall_id);
|
||||
|
||||
if (pptp_lnk != NULL) {
|
||||
int accumulate = *pcall_id;
|
||||
|
||||
/* De-alias the Peer's Call Id. */
|
||||
*pcall_id = GetOriginalPort(pptp_lnk);
|
||||
|
||||
/* Compute TCP checksum for modified packet */
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
accumulate -= *pcall_id;
|
||||
ADJUST_CHECKSUM(accumulate, tc->th_sum);
|
||||
|
||||
if (ctl_type == PPTP_OutCallReply || ctl_type == PPTP_InCallReply) {
|
||||
PptpCode codes = (PptpCode) (cptr + 1);
|
||||
|
||||
if (codes->resCode == 1) /* Connection
|
||||
* established, */
|
||||
SetDestCallId(pptp_lnk, /* note the Call ID. */
|
||||
cptr->cid1);
|
||||
else
|
||||
SetExpire(pptp_lnk, 0); /* Connection refused. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static 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 *)ip_next(pip);
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
tlen = ntohs(pip->ip_len);
|
||||
dlen = tlen - hlen;
|
||||
|
||||
/* Verify data length */
|
||||
if (dlen < (int)(sizeof(struct pptpMsgHead) + sizeof(struct pptpCallIds)))
|
||||
return (NULL);
|
||||
|
||||
/* Move up to PPTP message header */
|
||||
hptr = (PptpMsgHead) tcp_next(tc);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Verify data length. */
|
||||
if ((*ptype == PPTP_OutCallReply || *ptype == PPTP_InCallReply) &&
|
||||
(dlen < (int)(sizeof(struct pptpMsgHead) + sizeof(struct pptpCallIds) +
|
||||
sizeof(struct pptpCodes))))
|
||||
return (NULL);
|
||||
else
|
||||
return (PptpCallId) (hptr + 1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
AliasHandlePptpGreOut(struct libalias *la, struct ip *pip)
|
||||
{
|
||||
GreHdr *gr;
|
||||
struct alias_link *lnk;
|
||||
|
||||
gr = (GreHdr *) ip_next(pip);
|
||||
|
||||
/* Check GRE header bits. */
|
||||
if ((ntohl(*((u_int32_t *) gr)) & PPTP_INIT_MASK) != PPTP_INIT_VALUE)
|
||||
return (-1);
|
||||
|
||||
lnk = FindPptpOutByPeerCallId(la, pip->ip_src, pip->ip_dst, gr->gh_call_id);
|
||||
if (lnk != NULL) {
|
||||
struct in_addr alias_addr = GetAliasAddress(lnk);
|
||||
|
||||
/* Change source IP address. */
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
&alias_addr, &pip->ip_src, 2);
|
||||
pip->ip_src = alias_addr;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
AliasHandlePptpGreIn(struct libalias *la, struct ip *pip)
|
||||
{
|
||||
GreHdr *gr;
|
||||
struct alias_link *lnk;
|
||||
|
||||
gr = (GreHdr *) ip_next(pip);
|
||||
|
||||
/* Check GRE header bits. */
|
||||
if ((ntohl(*((u_int32_t *) gr)) & PPTP_INIT_MASK) != PPTP_INIT_VALUE)
|
||||
return (-1);
|
||||
|
||||
lnk = FindPptpInByPeerCallId(la, pip->ip_src, pip->ip_dst, gr->gh_call_id);
|
||||
if (lnk != NULL) {
|
||||
struct in_addr src_addr = GetOriginalAddress(lnk);
|
||||
|
||||
/* De-alias the Peer's Call Id. */
|
||||
gr->gh_call_id = GetOriginalPort(lnk);
|
||||
|
||||
/* Restore original IP address. */
|
||||
DifferentialChecksum(&pip->ip_sum,
|
||||
&src_addr, &pip->ip_dst, 2);
|
||||
pip->ip_dst = src_addr;
|
||||
}
|
||||
return (0);
|
||||
}
|
@ -1,812 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Charles Mott <cm@linktel.net>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* file: alias_proxy.c
|
||||
|
||||
This file encapsulates special operations related to transparent
|
||||
proxy redirection. This is where packets with a particular destination,
|
||||
usually tcp port 80, are redirected to a proxy server.
|
||||
|
||||
When packets are proxied, the destination address and port are
|
||||
modified. In certain cases, it is necessary to somehow encode
|
||||
the original address/port info into the packet. Two methods are
|
||||
presently supported: addition of a [DEST addr port] string at the
|
||||
beginning of a tcp stream, or inclusion of an optional field
|
||||
in the IP header.
|
||||
|
||||
There is one public API function:
|
||||
|
||||
PacketAliasProxyRule() -- Adds and deletes proxy
|
||||
rules.
|
||||
|
||||
Rules are stored in a linear linked list, so lookup efficiency
|
||||
won't be too good for large lists.
|
||||
|
||||
|
||||
Initial development: April, 1998 (cjm)
|
||||
*/
|
||||
|
||||
|
||||
/* System includes */
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/* BSD IPV4 includes */
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "alias_local.h" /* Functions used by alias*.c */
|
||||
#include "alias.h" /* Public API functions for libalias */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Data structures
|
||||
*/
|
||||
|
||||
/*
|
||||
* A linked list of arbitrary length, based on struct proxy_entry is
|
||||
* used to store proxy rules.
|
||||
*/
|
||||
struct proxy_entry {
|
||||
struct libalias *la;
|
||||
#define PROXY_TYPE_ENCODE_NONE 1
|
||||
#define PROXY_TYPE_ENCODE_TCPSTREAM 2
|
||||
#define PROXY_TYPE_ENCODE_IPHDR 3
|
||||
int rule_index;
|
||||
int proxy_type;
|
||||
u_char proto;
|
||||
u_short proxy_port;
|
||||
u_short server_port;
|
||||
|
||||
struct in_addr server_addr;
|
||||
|
||||
struct in_addr src_addr;
|
||||
struct in_addr src_mask;
|
||||
|
||||
struct in_addr dst_addr;
|
||||
struct in_addr dst_mask;
|
||||
|
||||
struct proxy_entry *next;
|
||||
struct proxy_entry *last;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
File scope variables
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Local (static) functions:
|
||||
|
||||
IpMask() -- Utility function for creating IP
|
||||
masks from integer (1-32) specification.
|
||||
IpAddr() -- Utility function for converting string
|
||||
to IP address
|
||||
IpPort() -- Utility function for converting string
|
||||
to port number
|
||||
RuleAdd() -- Adds an element to the rule list.
|
||||
RuleDelete() -- Removes an element from the rule list.
|
||||
RuleNumberDelete() -- Removes all elements from the rule list
|
||||
having a certain rule number.
|
||||
ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning
|
||||
of a TCP stream.
|
||||
ProxyEncodeIpHeader() -- Adds an IP option indicating the true
|
||||
destination of a proxied IP packet
|
||||
*/
|
||||
|
||||
static int IpMask(int, struct in_addr *);
|
||||
static int IpAddr(char *, struct in_addr *);
|
||||
static int IpPort(char *, int, int *);
|
||||
static void RuleAdd(struct libalias *la, struct proxy_entry *);
|
||||
static void RuleDelete(struct proxy_entry *);
|
||||
static int RuleNumberDelete(struct libalias *la, int);
|
||||
static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int);
|
||||
static void ProxyEncodeIpHeader(struct ip *, int);
|
||||
|
||||
static int
|
||||
IpMask(int nbits, struct in_addr *mask)
|
||||
{
|
||||
int i;
|
||||
u_int imask;
|
||||
|
||||
if (nbits < 0 || nbits > 32)
|
||||
return (-1);
|
||||
|
||||
imask = 0;
|
||||
for (i = 0; i < nbits; i++)
|
||||
imask = (imask >> 1) + 0x80000000;
|
||||
mask->s_addr = htonl(imask);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
IpAddr(char *s, struct in_addr *addr)
|
||||
{
|
||||
if (inet_aton(s, addr) == 0)
|
||||
return (-1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
IpPort(char *s, int proto, int *port)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = sscanf(s, "%d", port);
|
||||
if (n != 1) {
|
||||
struct servent *se;
|
||||
|
||||
if (proto == IPPROTO_TCP)
|
||||
se = getservbyname(s, "tcp");
|
||||
else if (proto == IPPROTO_UDP)
|
||||
se = getservbyname(s, "udp");
|
||||
else
|
||||
return (-1);
|
||||
|
||||
if (se == NULL)
|
||||
return (-1);
|
||||
|
||||
*port = (u_int) ntohs(se->s_port);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
RuleAdd(struct libalias *la, struct proxy_entry *entry)
|
||||
{
|
||||
int rule_index;
|
||||
struct proxy_entry *ptr;
|
||||
struct proxy_entry *ptr_last;
|
||||
|
||||
if (la->proxyList == NULL) {
|
||||
la->proxyList = entry;
|
||||
entry->last = NULL;
|
||||
entry->next = NULL;
|
||||
return;
|
||||
}
|
||||
entry->la = la;
|
||||
|
||||
rule_index = entry->rule_index;
|
||||
ptr = la->proxyList;
|
||||
ptr_last = NULL;
|
||||
while (ptr != NULL) {
|
||||
if (ptr->rule_index >= rule_index) {
|
||||
if (ptr_last == NULL) {
|
||||
entry->next = la->proxyList;
|
||||
entry->last = NULL;
|
||||
la->proxyList->last = entry;
|
||||
la->proxyList = entry;
|
||||
return;
|
||||
}
|
||||
ptr_last->next = entry;
|
||||
ptr->last = entry;
|
||||
entry->last = ptr->last;
|
||||
entry->next = ptr;
|
||||
return;
|
||||
}
|
||||
ptr_last = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
ptr_last->next = entry;
|
||||
entry->last = ptr_last;
|
||||
entry->next = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
RuleDelete(struct proxy_entry *entry)
|
||||
{
|
||||
struct libalias *la;
|
||||
|
||||
la = entry->la;
|
||||
if (entry->last != NULL)
|
||||
entry->last->next = entry->next;
|
||||
else
|
||||
la->proxyList = entry->next;
|
||||
|
||||
if (entry->next != NULL)
|
||||
entry->next->last = entry->last;
|
||||
|
||||
free(entry);
|
||||
}
|
||||
|
||||
static int
|
||||
RuleNumberDelete(struct libalias *la, int rule_index)
|
||||
{
|
||||
int err;
|
||||
struct proxy_entry *ptr;
|
||||
|
||||
err = -1;
|
||||
ptr = la->proxyList;
|
||||
while (ptr != NULL) {
|
||||
struct proxy_entry *ptr_next;
|
||||
|
||||
ptr_next = ptr->next;
|
||||
if (ptr->rule_index == rule_index) {
|
||||
err = 0;
|
||||
RuleDelete(ptr);
|
||||
}
|
||||
ptr = ptr_next;
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static void
|
||||
ProxyEncodeTcpStream(struct alias_link *lnk,
|
||||
struct ip *pip,
|
||||
int maxpacketsize)
|
||||
{
|
||||
int slen;
|
||||
char buffer[40];
|
||||
struct tcphdr *tc;
|
||||
|
||||
/* Compute pointer to tcp header */
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
|
||||
/* Don't modify if once already modified */
|
||||
|
||||
if (GetAckModified(lnk))
|
||||
return;
|
||||
|
||||
/* Translate destination address and port to string form */
|
||||
snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]",
|
||||
inet_ntoa(GetProxyAddress(lnk)), (u_int) ntohs(GetProxyPort(lnk)));
|
||||
|
||||
/* Pad string out to a multiple of two in length */
|
||||
slen = strlen(buffer);
|
||||
switch (slen % 2) {
|
||||
case 0:
|
||||
strcat(buffer, " \n");
|
||||
slen += 2;
|
||||
break;
|
||||
case 1:
|
||||
strcat(buffer, "\n");
|
||||
slen += 1;
|
||||
}
|
||||
|
||||
/* Check for packet overflow */
|
||||
if ((int)(ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize)
|
||||
return;
|
||||
|
||||
/* Shift existing TCP data and insert destination string */
|
||||
{
|
||||
int dlen;
|
||||
int hlen;
|
||||
u_char *p;
|
||||
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
dlen = ntohs(pip->ip_len) - hlen;
|
||||
|
||||
/* Modify first packet that has data in it */
|
||||
|
||||
if (dlen == 0)
|
||||
return;
|
||||
|
||||
p = (char *)pip;
|
||||
p += hlen;
|
||||
|
||||
memmove(p + slen, p, dlen);
|
||||
memcpy(p, buffer, slen);
|
||||
}
|
||||
|
||||
/* Save information about modfied sequence number */
|
||||
{
|
||||
int delta;
|
||||
|
||||
SetAckModified(lnk);
|
||||
delta = GetDeltaSeqOut(pip, lnk);
|
||||
AddSeq(pip, lnk, delta + slen);
|
||||
}
|
||||
|
||||
/* Update IP header packet length and checksum */
|
||||
{
|
||||
int accumulate;
|
||||
|
||||
accumulate = pip->ip_len;
|
||||
pip->ip_len = htons(ntohs(pip->ip_len) + slen);
|
||||
accumulate -= pip->ip_len;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
}
|
||||
|
||||
/* Update TCP checksum, Use TcpChecksum since so many things have
|
||||
already changed. */
|
||||
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
}
|
||||
|
||||
static void
|
||||
ProxyEncodeIpHeader(struct ip *pip,
|
||||
int maxpacketsize)
|
||||
{
|
||||
#define OPTION_LEN_BYTES 8
|
||||
#define OPTION_LEN_INT16 4
|
||||
#define OPTION_LEN_INT32 2
|
||||
u_char option[OPTION_LEN_BYTES];
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip));
|
||||
fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip));
|
||||
#endif
|
||||
|
||||
(void)maxpacketsize;
|
||||
|
||||
/* Check to see that there is room to add an IP option */
|
||||
if (pip->ip_hl > (0x0f - OPTION_LEN_INT32))
|
||||
return;
|
||||
|
||||
/* Build option and copy into packet */
|
||||
{
|
||||
u_char *ptr;
|
||||
struct tcphdr *tc;
|
||||
|
||||
ptr = (u_char *) pip;
|
||||
ptr += 20;
|
||||
memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20);
|
||||
|
||||
option[0] = 0x64; /* class: 3 (reserved), option 4 */
|
||||
option[1] = OPTION_LEN_BYTES;
|
||||
|
||||
memcpy(&option[2], (u_char *) & pip->ip_dst, 4);
|
||||
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
memcpy(&option[6], (u_char *) & tc->th_sport, 2);
|
||||
|
||||
memcpy(ptr, option, 8);
|
||||
}
|
||||
|
||||
/* Update checksum, header length and packet length */
|
||||
{
|
||||
int i;
|
||||
int accumulate;
|
||||
u_short *sptr;
|
||||
|
||||
sptr = (u_short *) option;
|
||||
accumulate = 0;
|
||||
for (i = 0; i < OPTION_LEN_INT16; i++)
|
||||
accumulate -= *(sptr++);
|
||||
|
||||
sptr = (u_short *) pip;
|
||||
accumulate += *sptr;
|
||||
pip->ip_hl += OPTION_LEN_INT32;
|
||||
accumulate -= *sptr;
|
||||
|
||||
accumulate += pip->ip_len;
|
||||
pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES);
|
||||
accumulate -= pip->ip_len;
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, pip->ip_sum);
|
||||
}
|
||||
#undef OPTION_LEN_BYTES
|
||||
#undef OPTION_LEN_INT16
|
||||
#undef OPTION_LEN_INT32
|
||||
#ifdef DEBUG
|
||||
fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip));
|
||||
fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Functions by other packet alias source files
|
||||
|
||||
ProxyCheck() -- Checks whether an outgoing packet should
|
||||
be proxied.
|
||||
ProxyModify() -- Encodes the original destination address/port
|
||||
for a packet which is to be redirected to
|
||||
a proxy server.
|
||||
*/
|
||||
|
||||
int
|
||||
ProxyCheck(struct libalias *la, struct ip *pip,
|
||||
struct in_addr *proxy_server_addr,
|
||||
u_short * proxy_server_port)
|
||||
{
|
||||
u_short dst_port;
|
||||
struct in_addr src_addr;
|
||||
struct in_addr dst_addr;
|
||||
struct proxy_entry *ptr;
|
||||
|
||||
src_addr = pip->ip_src;
|
||||
dst_addr = pip->ip_dst;
|
||||
dst_port = ((struct tcphdr *)ip_next(pip))
|
||||
->th_dport;
|
||||
|
||||
ptr = la->proxyList;
|
||||
while (ptr != NULL) {
|
||||
u_short proxy_port;
|
||||
|
||||
proxy_port = ptr->proxy_port;
|
||||
if ((dst_port == proxy_port || proxy_port == 0)
|
||||
&& pip->ip_p == ptr->proto
|
||||
&& src_addr.s_addr != ptr->server_addr.s_addr) {
|
||||
struct in_addr src_addr_masked;
|
||||
struct in_addr dst_addr_masked;
|
||||
|
||||
src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr;
|
||||
dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr;
|
||||
|
||||
if ((src_addr_masked.s_addr == ptr->src_addr.s_addr)
|
||||
&& (dst_addr_masked.s_addr == ptr->dst_addr.s_addr)) {
|
||||
if ((*proxy_server_port = ptr->server_port) == 0)
|
||||
*proxy_server_port = dst_port;
|
||||
*proxy_server_addr = ptr->server_addr;
|
||||
return (ptr->proxy_type);
|
||||
}
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ProxyModify(struct libalias *la, struct alias_link *lnk,
|
||||
struct ip *pip,
|
||||
int maxpacketsize,
|
||||
int proxy_type)
|
||||
{
|
||||
|
||||
(void)la;
|
||||
|
||||
switch (proxy_type) {
|
||||
case PROXY_TYPE_ENCODE_IPHDR:
|
||||
ProxyEncodeIpHeader(pip, maxpacketsize);
|
||||
break;
|
||||
|
||||
case PROXY_TYPE_ENCODE_TCPSTREAM:
|
||||
ProxyEncodeTcpStream(lnk, pip, maxpacketsize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Public API functions
|
||||
*/
|
||||
|
||||
int
|
||||
LibAliasProxyRule(struct libalias *la, const char *cmd)
|
||||
{
|
||||
/*
|
||||
* This function takes command strings of the form:
|
||||
*
|
||||
* server <addr>[:<port>]
|
||||
* [port <port>]
|
||||
* [rule n]
|
||||
* [proto tcp|udp]
|
||||
* [src <addr>[/n]]
|
||||
* [dst <addr>[/n]]
|
||||
* [type encode_tcp_stream|encode_ip_hdr|no_encode]
|
||||
*
|
||||
* delete <rule number>
|
||||
*
|
||||
* Subfields can be in arbitrary order. Port numbers and addresses
|
||||
* must be in either numeric or symbolic form. An optional rule number
|
||||
* is used to control the order in which rules are searched. If two
|
||||
* rules have the same number, then search order cannot be guaranteed,
|
||||
* and the rules should be disjoint. If no rule number is specified,
|
||||
* then 0 is used, and group 0 rules are always checked before any
|
||||
* others.
|
||||
*/
|
||||
int i, n, len;
|
||||
int cmd_len;
|
||||
int token_count;
|
||||
int state;
|
||||
char *token;
|
||||
char buffer[256];
|
||||
char str_port[sizeof(buffer)];
|
||||
char str_server_port[sizeof(buffer)];
|
||||
char *res = buffer;
|
||||
|
||||
int rule_index;
|
||||
int proto;
|
||||
int proxy_type;
|
||||
int proxy_port;
|
||||
int server_port;
|
||||
struct in_addr server_addr;
|
||||
struct in_addr src_addr, src_mask;
|
||||
struct in_addr dst_addr, dst_mask;
|
||||
struct proxy_entry *proxy_entry;
|
||||
|
||||
/* Copy command line into a buffer */
|
||||
cmd += strspn(cmd, " \t");
|
||||
cmd_len = strlen(cmd);
|
||||
if (cmd_len > (int)(sizeof(buffer) - 1))
|
||||
return (-1);
|
||||
strcpy(buffer, cmd);
|
||||
|
||||
/* Convert to lower case */
|
||||
len = strlen(buffer);
|
||||
for (i = 0; i < len; i++)
|
||||
buffer[i] = tolower((unsigned char)buffer[i]);
|
||||
|
||||
/* Set default proxy type */
|
||||
|
||||
/* Set up default values */
|
||||
rule_index = 0;
|
||||
proxy_type = PROXY_TYPE_ENCODE_NONE;
|
||||
proto = IPPROTO_TCP;
|
||||
proxy_port = 0;
|
||||
server_addr.s_addr = 0;
|
||||
server_port = 0;
|
||||
src_addr.s_addr = 0;
|
||||
IpMask(0, &src_mask);
|
||||
dst_addr.s_addr = 0;
|
||||
IpMask(0, &dst_mask);
|
||||
|
||||
str_port[0] = 0;
|
||||
str_server_port[0] = 0;
|
||||
|
||||
/* Parse command string with state machine */
|
||||
#define STATE_READ_KEYWORD 0
|
||||
#define STATE_READ_TYPE 1
|
||||
#define STATE_READ_PORT 2
|
||||
#define STATE_READ_SERVER 3
|
||||
#define STATE_READ_RULE 4
|
||||
#define STATE_READ_DELETE 5
|
||||
#define STATE_READ_PROTO 6
|
||||
#define STATE_READ_SRC 7
|
||||
#define STATE_READ_DST 8
|
||||
state = STATE_READ_KEYWORD;
|
||||
token = strsep(&res, " \t");
|
||||
token_count = 0;
|
||||
while (token != NULL) {
|
||||
token_count++;
|
||||
switch (state) {
|
||||
case STATE_READ_KEYWORD:
|
||||
if (strcmp(token, "type") == 0)
|
||||
state = STATE_READ_TYPE;
|
||||
else if (strcmp(token, "port") == 0)
|
||||
state = STATE_READ_PORT;
|
||||
else if (strcmp(token, "server") == 0)
|
||||
state = STATE_READ_SERVER;
|
||||
else if (strcmp(token, "rule") == 0)
|
||||
state = STATE_READ_RULE;
|
||||
else if (strcmp(token, "delete") == 0)
|
||||
state = STATE_READ_DELETE;
|
||||
else if (strcmp(token, "proto") == 0)
|
||||
state = STATE_READ_PROTO;
|
||||
else if (strcmp(token, "src") == 0)
|
||||
state = STATE_READ_SRC;
|
||||
else if (strcmp(token, "dst") == 0)
|
||||
state = STATE_READ_DST;
|
||||
else
|
||||
return (-1);
|
||||
break;
|
||||
|
||||
case STATE_READ_TYPE:
|
||||
if (strcmp(token, "encode_ip_hdr") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_IPHDR;
|
||||
else if (strcmp(token, "encode_tcp_stream") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
|
||||
else if (strcmp(token, "no_encode") == 0)
|
||||
proxy_type = PROXY_TYPE_ENCODE_NONE;
|
||||
else
|
||||
return (-1);
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_PORT:
|
||||
strcpy(str_port, token);
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_SERVER:
|
||||
{
|
||||
int err;
|
||||
char *p;
|
||||
char s[sizeof(buffer)];
|
||||
|
||||
p = token;
|
||||
while (*p != ':' && *p != 0)
|
||||
p++;
|
||||
|
||||
if (*p != ':') {
|
||||
err = IpAddr(token, &server_addr);
|
||||
if (err)
|
||||
return (-1);
|
||||
} else {
|
||||
*p = ' ';
|
||||
|
||||
n = sscanf(token, "%s %s", s, str_server_port);
|
||||
if (n != 2)
|
||||
return (-1);
|
||||
|
||||
err = IpAddr(s, &server_addr);
|
||||
if (err)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_RULE:
|
||||
n = sscanf(token, "%d", &rule_index);
|
||||
if (n != 1 || rule_index < 0)
|
||||
return (-1);
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_DELETE:
|
||||
{
|
||||
int err;
|
||||
int rule_to_delete;
|
||||
|
||||
if (token_count != 2)
|
||||
return (-1);
|
||||
|
||||
n = sscanf(token, "%d", &rule_to_delete);
|
||||
if (n != 1)
|
||||
return (-1);
|
||||
err = RuleNumberDelete(la, rule_to_delete);
|
||||
if (err)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
case STATE_READ_PROTO:
|
||||
if (strcmp(token, "tcp") == 0)
|
||||
proto = IPPROTO_TCP;
|
||||
else if (strcmp(token, "udp") == 0)
|
||||
proto = IPPROTO_UDP;
|
||||
else
|
||||
return (-1);
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
case STATE_READ_SRC:
|
||||
case STATE_READ_DST:
|
||||
{
|
||||
int err;
|
||||
char *p;
|
||||
struct in_addr mask;
|
||||
struct in_addr addr;
|
||||
|
||||
p = token;
|
||||
while (*p != '/' && *p != 0)
|
||||
p++;
|
||||
|
||||
if (*p != '/') {
|
||||
IpMask(32, &mask);
|
||||
err = IpAddr(token, &addr);
|
||||
if (err)
|
||||
return (-1);
|
||||
} else {
|
||||
int nbits;
|
||||
char s[sizeof(buffer)];
|
||||
|
||||
*p = ' ';
|
||||
n = sscanf(token, "%s %d", s, &nbits);
|
||||
if (n != 2)
|
||||
return (-1);
|
||||
|
||||
err = IpAddr(s, &addr);
|
||||
if (err)
|
||||
return (-1);
|
||||
|
||||
err = IpMask(nbits, &mask);
|
||||
if (err)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (state == STATE_READ_SRC) {
|
||||
src_addr = addr;
|
||||
src_mask = mask;
|
||||
} else {
|
||||
dst_addr = addr;
|
||||
dst_mask = mask;
|
||||
}
|
||||
}
|
||||
state = STATE_READ_KEYWORD;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (-1);
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
token = strsep(&res, " \t");
|
||||
} while (token != NULL && !*token);
|
||||
}
|
||||
#undef STATE_READ_KEYWORD
|
||||
#undef STATE_READ_TYPE
|
||||
#undef STATE_READ_PORT
|
||||
#undef STATE_READ_SERVER
|
||||
#undef STATE_READ_RULE
|
||||
#undef STATE_READ_DELETE
|
||||
#undef STATE_READ_PROTO
|
||||
#undef STATE_READ_SRC
|
||||
#undef STATE_READ_DST
|
||||
|
||||
/* Convert port strings to numbers. This needs to be done after
|
||||
the string is parsed, because the prototype might not be designated
|
||||
before the ports (which might be symbolic entries in /etc/services) */
|
||||
|
||||
if (strlen(str_port) != 0) {
|
||||
int err;
|
||||
|
||||
err = IpPort(str_port, proto, &proxy_port);
|
||||
if (err)
|
||||
return (-1);
|
||||
} else {
|
||||
proxy_port = 0;
|
||||
}
|
||||
|
||||
if (strlen(str_server_port) != 0) {
|
||||
int err;
|
||||
|
||||
err = IpPort(str_server_port, proto, &server_port);
|
||||
if (err)
|
||||
return (-1);
|
||||
} else {
|
||||
server_port = 0;
|
||||
}
|
||||
|
||||
/* Check that at least the server address has been defined */
|
||||
if (server_addr.s_addr == 0)
|
||||
return (-1);
|
||||
|
||||
/* Add to linked list */
|
||||
proxy_entry = malloc(sizeof(struct proxy_entry));
|
||||
if (proxy_entry == NULL)
|
||||
return (-1);
|
||||
|
||||
proxy_entry->proxy_type = proxy_type;
|
||||
proxy_entry->rule_index = rule_index;
|
||||
proxy_entry->proto = proto;
|
||||
proxy_entry->proxy_port = htons(proxy_port);
|
||||
proxy_entry->server_port = htons(server_port);
|
||||
proxy_entry->server_addr = server_addr;
|
||||
proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr;
|
||||
proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr;
|
||||
proxy_entry->src_mask = src_mask;
|
||||
proxy_entry->dst_mask = dst_mask;
|
||||
|
||||
RuleAdd(la, proxy_entry);
|
||||
|
||||
return (0);
|
||||
}
|
@ -1,350 +0,0 @@
|
||||
/*-
|
||||
* alias_skinny.c
|
||||
*
|
||||
* Copyright (c) 2002, 2003 MarcusCom, Inc.
|
||||
* 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.
|
||||
*
|
||||
* Author: Joe Marcus Clarke <marcus@FreeBSD.org>
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alias_local.h"
|
||||
|
||||
/*
|
||||
* alias_skinny.c handles the translation for the Cisco Skinny Station
|
||||
* protocol. Skinny typically uses TCP port 2000 to set up calls between
|
||||
* a Cisco Call Manager and a Cisco IP phone. When a phone comes on line,
|
||||
* it first needs to register with the Call Manager. To do this it sends
|
||||
* a registration message. This message contains the IP address of the
|
||||
* IP phone. This message must then be translated to reflect our global
|
||||
* IP address. Along with the registration message (and usually in the
|
||||
* same packet), the phone sends an IP port message. This message indicates
|
||||
* the TCP port over which it will communicate.
|
||||
*
|
||||
* When a call is placed from the phone, the Call Manager will send an
|
||||
* Open Receive Channel message to the phone to let the caller know someone
|
||||
* has answered. The phone then sends back an Open Receive Channel
|
||||
* Acknowledgement. In this packet, the phone sends its IP address again,
|
||||
* and the UDP port over which the voice traffic should flow. These values
|
||||
* need translation. Right after the Open Receive Channel Acknowledgement,
|
||||
* the Call Manager sends a Start Media Transmission message indicating the
|
||||
* call is connected. This message contains the IP address and UDP port
|
||||
* number of the remote (called) party. Once this message is translated, the
|
||||
* call can commence. The called part sends the first UDP packet to the
|
||||
* calling phone at the pre-arranged UDP port in the Open Receive Channel
|
||||
* Acknowledgement.
|
||||
*
|
||||
* Skinny is a Cisco-proprietary protocol and is a trademark of Cisco Systems,
|
||||
* Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
|
||||
/* Message types that need translating */
|
||||
#define REG_MSG 0x00000001
|
||||
#define IP_PORT_MSG 0x00000002
|
||||
#define OPNRCVCH_ACK 0x00000022
|
||||
#define START_MEDIATX 0x0000008a
|
||||
|
||||
struct skinny_header {
|
||||
u_int32_t len;
|
||||
u_int32_t reserved;
|
||||
u_int32_t msgId;
|
||||
};
|
||||
|
||||
struct RegisterMessage {
|
||||
u_int32_t msgId;
|
||||
char devName [16];
|
||||
u_int32_t uid;
|
||||
u_int32_t instance;
|
||||
u_int32_t ipAddr;
|
||||
u_char devType;
|
||||
u_int32_t maxStreams;
|
||||
};
|
||||
|
||||
struct IpPortMessage {
|
||||
u_int32_t msgId;
|
||||
u_int32_t stationIpPort; /* Note: Skinny uses 32-bit port
|
||||
* numbers */
|
||||
};
|
||||
|
||||
struct OpenReceiveChannelAck {
|
||||
u_int32_t msgId;
|
||||
u_int32_t status;
|
||||
u_int32_t ipAddr;
|
||||
u_int32_t port;
|
||||
u_int32_t passThruPartyID;
|
||||
};
|
||||
|
||||
struct StartMediaTransmission {
|
||||
u_int32_t msgId;
|
||||
u_int32_t conferenceID;
|
||||
u_int32_t passThruPartyID;
|
||||
u_int32_t remoteIpAddr;
|
||||
u_int32_t remotePort;
|
||||
u_int32_t MSPacket;
|
||||
u_int32_t payloadCap;
|
||||
u_int32_t precedence;
|
||||
u_int32_t silenceSuppression;
|
||||
u_short maxFramesPerPacket;
|
||||
u_int32_t G723BitRate;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ClientToServer = 0,
|
||||
ServerToClient = 1
|
||||
} ConvDirection;
|
||||
|
||||
|
||||
static int
|
||||
alias_skinny_reg_msg(struct RegisterMessage *reg_msg, struct ip *pip,
|
||||
struct tcphdr *tc, struct alias_link *lnk,
|
||||
ConvDirection direction)
|
||||
{
|
||||
(void)direction;
|
||||
|
||||
reg_msg->ipAddr = (u_int32_t) GetAliasAddress(lnk).s_addr;
|
||||
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
alias_skinny_startmedia(struct StartMediaTransmission *start_media,
|
||||
struct ip *pip, struct tcphdr *tc,
|
||||
struct alias_link *lnk, u_int32_t localIpAddr,
|
||||
ConvDirection direction)
|
||||
{
|
||||
struct in_addr dst, src;
|
||||
|
||||
(void)pip;
|
||||
(void)tc;
|
||||
(void)lnk;
|
||||
(void)direction;
|
||||
|
||||
dst.s_addr = start_media->remoteIpAddr;
|
||||
src.s_addr = localIpAddr;
|
||||
|
||||
/*
|
||||
* XXX I should probably handle in bound global translations as
|
||||
* well.
|
||||
*/
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
alias_skinny_port_msg(struct IpPortMessage *port_msg, struct ip *pip,
|
||||
struct tcphdr *tc, struct alias_link *lnk,
|
||||
ConvDirection direction)
|
||||
{
|
||||
(void)direction;
|
||||
|
||||
port_msg->stationIpPort = (u_int32_t) ntohs(GetAliasPort(lnk));
|
||||
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
alias_skinny_opnrcvch_ack(struct libalias *la, struct OpenReceiveChannelAck *opnrcvch_ack,
|
||||
struct ip *pip, struct tcphdr *tc,
|
||||
struct alias_link *lnk, u_int32_t * localIpAddr,
|
||||
ConvDirection direction)
|
||||
{
|
||||
struct in_addr null_addr;
|
||||
struct alias_link *opnrcv_lnk;
|
||||
u_int32_t localPort;
|
||||
|
||||
(void)lnk;
|
||||
(void)direction;
|
||||
|
||||
*localIpAddr = (u_int32_t) opnrcvch_ack->ipAddr;
|
||||
localPort = opnrcvch_ack->port;
|
||||
|
||||
null_addr.s_addr = INADDR_ANY;
|
||||
opnrcv_lnk = FindUdpTcpOut(la, pip->ip_src, null_addr,
|
||||
htons((u_short) opnrcvch_ack->port), 0,
|
||||
IPPROTO_UDP, 1);
|
||||
opnrcvch_ack->ipAddr = (u_int32_t) GetAliasAddress(opnrcv_lnk).s_addr;
|
||||
opnrcvch_ack->port = (u_int32_t) ntohs(GetAliasPort(opnrcv_lnk));
|
||||
|
||||
tc->th_sum = 0;
|
||||
tc->th_sum = TcpChecksum(pip);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
AliasHandleSkinny(struct libalias *la, struct ip *pip, struct alias_link *lnk)
|
||||
{
|
||||
size_t hlen, tlen, dlen;
|
||||
struct tcphdr *tc;
|
||||
u_int32_t msgId, t, len, lip;
|
||||
struct skinny_header *sd;
|
||||
size_t orig_len, skinny_hdr_len = sizeof(struct skinny_header);
|
||||
ConvDirection direction;
|
||||
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
hlen = (pip->ip_hl + tc->th_off) << 2;
|
||||
tlen = ntohs(pip->ip_len);
|
||||
dlen = tlen - hlen;
|
||||
|
||||
sd = (struct skinny_header *)tcp_next(tc);
|
||||
|
||||
/*
|
||||
* XXX This direction is reserved for future use. I still need to
|
||||
* handle the scenario where the call manager is on the inside, and
|
||||
* the calling phone is on the global outside.
|
||||
*/
|
||||
if (ntohs(tc->th_dport) == la->skinnyPort) {
|
||||
direction = ClientToServer;
|
||||
} else if (ntohs(tc->th_sport) == la->skinnyPort) {
|
||||
direction = ServerToClient;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Invalid port number, not a Skinny packet\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
orig_len = dlen;
|
||||
/*
|
||||
* Skinny packets can contain many messages. We need to loop
|
||||
* through the packet using len to determine message boundaries.
|
||||
* This comes into play big time with port messages being in the
|
||||
* same packet as register messages. Also, open receive channel
|
||||
* acks are usually buried in a pakcet some 400 bytes long.
|
||||
*/
|
||||
while (dlen >= skinny_hdr_len) {
|
||||
len = (sd->len);
|
||||
msgId = (sd->msgId);
|
||||
t = len;
|
||||
|
||||
if (t > orig_len || t > dlen) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Not a skinny packet, invalid length \n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
switch (msgId) {
|
||||
case REG_MSG: {
|
||||
struct RegisterMessage *reg_mesg;
|
||||
|
||||
if (len < (int)sizeof(struct RegisterMessage)) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Not a skinny packet, bad registration message\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
reg_mesg = (struct RegisterMessage *)&sd->msgId;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Received a register message");
|
||||
#endif
|
||||
alias_skinny_reg_msg(reg_mesg, pip, tc, lnk, direction);
|
||||
break;
|
||||
}
|
||||
case IP_PORT_MSG: {
|
||||
struct IpPortMessage *port_mesg;
|
||||
|
||||
if (len < (int)sizeof(struct IpPortMessage)) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Not a skinny packet, port message\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Received ipport message\n");
|
||||
#endif
|
||||
port_mesg = (struct IpPortMessage *)&sd->msgId;
|
||||
alias_skinny_port_msg(port_mesg, pip, tc, lnk, direction);
|
||||
break;
|
||||
}
|
||||
case OPNRCVCH_ACK: {
|
||||
struct OpenReceiveChannelAck *opnrcvchn_ack;
|
||||
|
||||
if (len < (int)sizeof(struct OpenReceiveChannelAck)) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Not a skinny packet, packet,OpnRcvChnAckMsg\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Received open rcv channel msg\n");
|
||||
#endif
|
||||
opnrcvchn_ack = (struct OpenReceiveChannelAck *)&sd->msgId;
|
||||
alias_skinny_opnrcvch_ack(la, opnrcvchn_ack, pip, tc, lnk, &lip, direction);
|
||||
break;
|
||||
}
|
||||
case START_MEDIATX: {
|
||||
struct StartMediaTransmission *startmedia_tx;
|
||||
|
||||
if (len < (int)sizeof(struct StartMediaTransmission)) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Not a skinny packet,StartMediaTx Message\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"PacketAlias/Skinny: Received start media trans msg\n");
|
||||
#endif
|
||||
startmedia_tx = (struct StartMediaTransmission *)&sd->msgId;
|
||||
alias_skinny_startmedia(startmedia_tx, pip, tc, lnk, lip, direction);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Place the pointer at the next message in the packet. */
|
||||
dlen -= len + (skinny_hdr_len - sizeof(msgId));
|
||||
sd = (struct skinny_header *)(((char *)&sd->msgId) + len);
|
||||
}
|
||||
}
|
@ -1,445 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$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'))
|
||||
|
||||
static int
|
||||
search_string(char *data, int dlen, const 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);
|
||||
}
|
||||
|
||||
static int
|
||||
alias_rtsp_out(struct libalias *la, struct ip *pip,
|
||||
struct alias_link *lnk,
|
||||
char *data,
|
||||
const 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;
|
||||
const char *transport_str = "transport:";
|
||||
char newdata[2048], *port_data, *port_newdata, stemp[80];
|
||||
int links_created = 0, pkt_updated = 0;
|
||||
struct alias_link *rtsp_lnk = NULL;
|
||||
struct in_addr null_addr;
|
||||
|
||||
/* Calculate data length of TCP packet */
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
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 > (int)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(la, null_addr,
|
||||
FindAliasAddress(la, 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_lnk = FindRtspOut(la, GetOriginalAddress(lnk), null_addr,
|
||||
htons(base_port + j), htons(base_alias + j),
|
||||
IPPROTO_UDP);
|
||||
if (rtsp_lnk != NULL) {
|
||||
#ifndef NO_FW_PUNCH
|
||||
/*
|
||||
* Punch
|
||||
* hole in
|
||||
* firewall
|
||||
*/
|
||||
PunchFWHole(rtsp_lnk);
|
||||
#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_lnk) {
|
||||
|
||||
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(lnk);
|
||||
delta = GetDeltaSeqOut(pip, lnk);
|
||||
AddSeq(pip, lnk, 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 */
|
||||
|
||||
static int
|
||||
alias_pna_out(struct libalias *la, struct ip *pip,
|
||||
struct alias_link *lnk,
|
||||
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(&port, work, 2);
|
||||
pna_links = FindUdpTcpOut(la, pip->ip_src, GetDestAddress(lnk),
|
||||
port, 0, IPPROTO_UDP, 1);
|
||||
if (pna_links != NULL) {
|
||||
#ifndef NO_FW_PUNCH
|
||||
/* Punch hole in firewall */
|
||||
PunchFWHole(pna_links);
|
||||
#endif
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
alias_port = GetAliasPort(pna_links);
|
||||
memcpy(work, &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 libalias *la, struct ip *pip, struct alias_link *lnk, int maxpacketsize)
|
||||
{
|
||||
int hlen, tlen, dlen;
|
||||
struct tcphdr *tc;
|
||||
char *data;
|
||||
const char *setup = "SETUP", *pna = "PNA", *str200 = "200";
|
||||
const char *okstr = "OK", *client_port_str = "client_port";
|
||||
const char *server_port_str = "server_port";
|
||||
int i, parseOk;
|
||||
|
||||
(void)maxpacketsize;
|
||||
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
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 >= (int)strlen(setup)) {
|
||||
if (memcmp(data, setup, strlen(setup)) == 0) {
|
||||
alias_rtsp_out(la, pip, lnk, data, client_port_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dlen >= (int)strlen(pna)) {
|
||||
if (memcmp(data, pna, strlen(pna)) == 0) {
|
||||
alias_pna_out(la, pip, lnk, data, dlen);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* When aliasing a server, check for the 200 reply
|
||||
* Accomodate varying number of blanks between 200 & OK
|
||||
*/
|
||||
|
||||
if (dlen >= (int)strlen(str200)) {
|
||||
|
||||
for (parseOk = 0, i = 0;
|
||||
i <= dlen - (int)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) >= (int)strlen(okstr)) {
|
||||
|
||||
if (memcmp(&data[i], okstr, strlen(okstr)) == 0)
|
||||
alias_rtsp_out(la, pip, lnk, data, server_port_str);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Charles Mott <cm@linktel.net>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
/*
|
||||
Alias_util.c contains general utilities used by other functions
|
||||
in the packet aliasing module. At the moment, there are functions
|
||||
for computing IP header and TCP packet checksums.
|
||||
|
||||
The checksum routines are based upon example code in a Unix networking
|
||||
text written by Stevens (sorry, I can't remember the title -- but
|
||||
at least this is a good author).
|
||||
|
||||
Initial Version: August, 1996 (cjm)
|
||||
|
||||
Version 1.7: January 9, 1997
|
||||
Added differential checksum update function.
|
||||
*/
|
||||
|
||||
/*
|
||||
Note: the checksum routines assume that the actual checksum word has
|
||||
been zeroed out. If the checksum word is filled with the proper value,
|
||||
then these routines will give a result of zero (useful for testing
|
||||
purposes);
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include "alias.h"
|
||||
#include "alias_local.h"
|
||||
|
||||
u_short
|
||||
LibAliasInternetChecksum(struct libalias *la, u_short * ptr, int nbytes)
|
||||
{
|
||||
int sum, oddbyte;
|
||||
|
||||
(void)la;
|
||||
|
||||
sum = 0;
|
||||
while (nbytes > 1) {
|
||||
sum += *ptr++;
|
||||
nbytes -= 2;
|
||||
}
|
||||
if (nbytes == 1) {
|
||||
oddbyte = 0;
|
||||
((u_char *) & oddbyte)[0] = *(u_char *) ptr;
|
||||
((u_char *) & oddbyte)[1] = 0;
|
||||
sum += oddbyte;
|
||||
}
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
return (~sum);
|
||||
}
|
||||
|
||||
u_short
|
||||
IpChecksum(struct ip *pip)
|
||||
{
|
||||
return (PacketAliasInternetChecksum((u_short *) pip,
|
||||
(pip->ip_hl << 2)));
|
||||
|
||||
}
|
||||
|
||||
u_short
|
||||
TcpChecksum(struct ip *pip)
|
||||
{
|
||||
u_short *ptr;
|
||||
struct tcphdr *tc;
|
||||
int nhdr, ntcp, nbytes;
|
||||
int sum, oddbyte;
|
||||
|
||||
nhdr = pip->ip_hl << 2;
|
||||
ntcp = ntohs(pip->ip_len) - nhdr;
|
||||
|
||||
tc = (struct tcphdr *)ip_next(pip);
|
||||
ptr = (u_short *) tc;
|
||||
|
||||
/* Add up TCP header and data */
|
||||
nbytes = ntcp;
|
||||
sum = 0;
|
||||
while (nbytes > 1) {
|
||||
sum += *ptr++;
|
||||
nbytes -= 2;
|
||||
}
|
||||
if (nbytes == 1) {
|
||||
oddbyte = 0;
|
||||
((u_char *) & oddbyte)[0] = *(u_char *) ptr;
|
||||
((u_char *) & oddbyte)[1] = 0;
|
||||
sum += oddbyte;
|
||||
}
|
||||
/* "Pseudo-header" data */
|
||||
ptr = (u_short *) & (pip->ip_dst);
|
||||
sum += *ptr++;
|
||||
sum += *ptr;
|
||||
ptr = (u_short *) & (pip->ip_src);
|
||||
sum += *ptr++;
|
||||
sum += *ptr;
|
||||
sum += htons((u_short) ntcp);
|
||||
sum += htons((u_short) pip->ip_p);
|
||||
|
||||
/* Roll over carry bits */
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
|
||||
/* Return checksum */
|
||||
return ((u_short) ~ sum);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DifferentialChecksum(u_short * cksum, void *newp, void *oldp, int n)
|
||||
{
|
||||
int i;
|
||||
int accumulate;
|
||||
u_short *new = newp;
|
||||
u_short *old = oldp;
|
||||
|
||||
accumulate = *cksum;
|
||||
for (i = 0; i < n; i++) {
|
||||
accumulate -= *new++;
|
||||
accumulate += *old++;
|
||||
}
|
||||
|
||||
if (accumulate < 0) {
|
||||
accumulate = -accumulate;
|
||||
accumulate = (accumulate >> 16) + (accumulate & 0xffff);
|
||||
accumulate += accumulate >> 16;
|
||||
*cksum = (u_short) ~ accumulate;
|
||||
} else {
|
||||
accumulate = (accumulate >> 16) + (accumulate & 0xffff);
|
||||
accumulate += accumulate >> 16;
|
||||
*cksum = (u_short) accumulate;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user