Build userland libalias using src/sys/netinet/libalias.

Reviewed by:	ru
Repocopy by:	peter
This commit is contained in:
Gleb Smirnoff 2005-05-04 12:49:44 +00:00
parent 5d6d6d382f
commit e0408a6edc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=145862
17 changed files with 2 additions and 10259 deletions

View File

@ -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.

View File

@ -1,5 +1,7 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../sys/netinet/libalias
LIB= alias
SHLIBDIR?= /lib
SHLIB_MAJOR= 4

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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

View File

@ -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
}
}

View File

@ -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.
*/

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}

View File

@ -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