diff --git a/lib/libalias/HISTORY b/lib/libalias/HISTORY deleted file mode 100644 index c5bca59cac1f..000000000000 --- a/lib/libalias/HISTORY +++ /dev/null @@ -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 ) - - 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 . - -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. diff --git a/lib/libalias/Makefile b/lib/libalias/Makefile index dc6eb2df2617..448346738298 100644 --- a/lib/libalias/Makefile +++ b/lib/libalias/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.PATH: ${.CURDIR}/../../sys/netinet/libalias + LIB= alias SHLIBDIR?= /lib SHLIB_MAJOR= 4 diff --git a/lib/libalias/alias.c b/lib/libalias/alias.c deleted file mode 100644 index 053c18dc997a..000000000000 --- a/lib/libalias/alias.c +++ /dev/null @@ -1,1433 +0,0 @@ -/*- - * Copyright (c) 2001 Charles Mott - * 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 -__FBSDID("$FreeBSD$"); - -/* - Alias.c provides supervisory control for the functions of the - packet aliasing software. It consists of routines to monitor - TCP connection state, protocol-specific aliasing routines, - fragment handling and the following outside world functional - interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn, - PacketAliasIn and PacketAliasOut. - - The other C program files are briefly described. The data - structure framework which holds information needed to translate - packets is encapsulated in alias_db.c. Data is accessed by - function calls, so other segments of the program need not know - about the underlying data structures. Alias_ftp.c contains - special code for modifying the ftp PORT command used to establish - data connections, while alias_irc.c does the same for IRC - DCC. Alias_util.c contains a few utility routines. - - Version 1.0 August, 1996 (cjm) - - Version 1.1 August 20, 1996 (cjm) - PPP host accepts incoming connections for ports 0 to 1023. - (Gary Roberts pointed out the need to handle incoming - connections.) - - Version 1.2 September 7, 1996 (cjm) - Fragment handling error in alias_db.c corrected. - (Tom Torrance helped fix this problem.) - - Version 1.4 September 16, 1996 (cjm) - - A more generalized method for handling incoming - connections, without the 0-1023 restriction, is - implemented in alias_db.c - - Improved ICMP support in alias.c. Traceroute - packet streams can now be correctly aliased. - - TCP connection closing logic simplified in - alias.c and now allows for additional 1 minute - "grace period" after FIN or RST is observed. - - Version 1.5 September 17, 1996 (cjm) - Corrected error in handling incoming UDP packets with 0 checksum. - (Tom Torrance helped fix this problem.) - - Version 1.6 September 18, 1996 (cjm) - Simplified ICMP aliasing scheme. Should now support - traceroute from Win95 as well as FreeBSD. - - Version 1.7 January 9, 1997 (cjm) - - Out-of-order fragment handling. - - IP checksum error fixed for ftp transfers - from aliasing host. - - Integer return codes added to all - aliasing/de-aliasing functions. - - Some obsolete comments cleaned up. - - Differential checksum computations for - IP header (TCP, UDP and ICMP were already - differential). - - Version 2.1 May 1997 (cjm) - - Added support for outgoing ICMP error - messages. - - Added two functions PacketAliasIn2() - and PacketAliasOut2() for dynamic address - control (e.g. round-robin allocation of - incoming packets). - - Version 2.2 July 1997 (cjm) - - Rationalized API function names to begin - with "PacketAlias..." - - Eliminated PacketAliasIn2() and - PacketAliasOut2() as poorly conceived. - - Version 2.3 Dec 1998 (dillon) - - Major bounds checking additions, see FreeBSD/CVS - - Version 3.1 May, 2000 (salander) - - Added hooks to handle PPTP. - - Version 3.2 July, 2000 (salander and satoh) - - Added PacketUnaliasOut routine. - - Added hooks to handle RTSP/RTP. - - See HISTORY file for additional revisions. -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "alias_local.h" -#include "alias.h" - -#define NETBIOS_NS_PORT_NUMBER 137 -#define NETBIOS_DGM_PORT_NUMBER 138 -#define FTP_CONTROL_PORT_NUMBER 21 -#define IRC_CONTROL_PORT_NUMBER_1 6667 -#define IRC_CONTROL_PORT_NUMBER_2 6668 -#define CUSEEME_PORT_NUMBER 7648 -#define RTSP_CONTROL_PORT_NUMBER_1 554 -#define RTSP_CONTROL_PORT_NUMBER_2 7070 -#define TFTP_PORT_NUMBER 69 -#define PPTP_CONTROL_PORT_NUMBER 1723 - -static __inline int -twowords(void *p) -{ - uint8_t *c = p; - -#if BYTE_ORDER == LITTLE_ENDIAN - uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0]; - uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2]; -#else - uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1]; - uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3]; -#endif - return (s1 + s2); -} - -/* TCP Handling Routines - - TcpMonitorIn() -- These routines monitor TCP connections, and - TcpMonitorOut() delete a link when a connection is closed. - -These routines look for SYN, FIN and RST flags to determine when TCP -connections open and close. When a TCP connection closes, the data -structure containing packet aliasing information is deleted after -a timeout period. -*/ - -/* Local prototypes */ -static void TcpMonitorIn(struct ip *, struct alias_link *); - -static void TcpMonitorOut(struct ip *, struct alias_link *); - - -static void -TcpMonitorIn(struct ip *pip, struct alias_link *lnk) -{ - struct tcphdr *tc; - - tc = (struct tcphdr *)ip_next(pip); - - switch (GetStateIn(lnk)) { - case ALIAS_TCP_STATE_NOT_CONNECTED: - if (tc->th_flags & TH_RST) - SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED); - else if (tc->th_flags & TH_SYN) - SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED); - break; - case ALIAS_TCP_STATE_CONNECTED: - if (tc->th_flags & (TH_FIN | TH_RST)) - SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED); - break; - } -} - -static void -TcpMonitorOut(struct ip *pip, struct alias_link *lnk) -{ - struct tcphdr *tc; - - tc = (struct tcphdr *)ip_next(pip); - - switch (GetStateOut(lnk)) { - case ALIAS_TCP_STATE_NOT_CONNECTED: - if (tc->th_flags & TH_RST) - SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED); - else if (tc->th_flags & TH_SYN) - SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED); - break; - case ALIAS_TCP_STATE_CONNECTED: - if (tc->th_flags & (TH_FIN | TH_RST)) - SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED); - break; - } -} - - - - - -/* Protocol Specific Packet Aliasing Routines - - IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2() - IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2() - ProtoAliasIn(), ProtoAliasOut() - UdpAliasIn(), UdpAliasOut() - TcpAliasIn(), TcpAliasOut() - -These routines handle protocol specific details of packet aliasing. -One may observe a certain amount of repetitive arithmetic in these -functions, the purpose of which is to compute a revised checksum -without actually summing over the entire data packet, which could be -unnecessarily time consuming. - -The purpose of the packet aliasing routines is to replace the source -address of the outgoing packet and then correctly put it back for -any incoming packets. For TCP and UDP, ports are also re-mapped. - -For ICMP echo/timestamp requests and replies, the following scheme -is used: the ID number is replaced by an alias for the outgoing -packet. - -ICMP error messages are handled by looking at the IP fragment -in the data section of the message. - -For TCP and UDP protocols, a port number is chosen for an outgoing -packet, and then incoming packets are identified by IP address and -port numbers. For TCP packets, there is additional logic in the event -that sequence and ACK numbers have been altered (as in the case for -FTP data port commands). - -The port numbers used by the packet aliasing module are not true -ports in the Unix sense. No sockets are actually bound to ports. -They are more correctly thought of as placeholders. - -All packets go through the aliasing mechanism, whether they come from -the gateway machine or other machines on a local area network. -*/ - - -/* Local prototypes */ -static int IcmpAliasIn1(struct libalias *, struct ip *); -static int IcmpAliasIn2(struct libalias *, struct ip *); -static int IcmpAliasIn(struct libalias *, struct ip *); - -static int IcmpAliasOut1(struct libalias *, struct ip *, int create); -static int IcmpAliasOut2(struct libalias *, struct ip *); -static int IcmpAliasOut(struct libalias *, struct ip *, int create); - -static int ProtoAliasIn(struct libalias *, struct ip *); -static int ProtoAliasOut(struct libalias *, struct ip *, int create); - -static int UdpAliasIn(struct libalias *, struct ip *); -static int UdpAliasOut(struct libalias *, struct ip *, int create); - -static int TcpAliasIn(struct libalias *, struct ip *); -static int TcpAliasOut(struct libalias *, struct ip *, int, int create); - - -static int -IcmpAliasIn1(struct libalias *la, struct ip *pip) -{ -/* - De-alias incoming echo and timestamp replies. - Alias incoming echo and timestamp requests. -*/ - struct alias_link *lnk; - struct icmp *ic; - - ic = (struct icmp *)ip_next(pip); - -/* Get source address from ICMP data field and restore original data */ - lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1); - if (lnk != NULL) { - u_short original_id; - int accumulate; - - original_id = GetOriginalPort(lnk); - -/* Adjust ICMP checksum */ - accumulate = ic->icmp_id; - accumulate -= original_id; - ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); - -/* Put original sequence number back in */ - ic->icmp_id = original_id; - -/* Put original address back into IP header */ - { - struct in_addr original_address; - - original_address = GetOriginalAddress(lnk); - DifferentialChecksum(&pip->ip_sum, - &original_address, &pip->ip_dst, 2); - pip->ip_dst = original_address; - } - - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - -static int -IcmpAliasIn2(struct libalias *la, struct ip *pip) -{ -/* - Alias incoming ICMP error messages containing - IP header and first 64 bits of datagram. -*/ - struct ip *ip; - struct icmp *ic, *ic2; - struct udphdr *ud; - struct tcphdr *tc; - struct alias_link *lnk; - - ic = (struct icmp *)ip_next(pip); - ip = &ic->icmp_ip; - - ud = (struct udphdr *)ip_next(ip); - tc = (struct tcphdr *)ip_next(ip); - ic2 = (struct icmp *)ip_next(ip); - - if (ip->ip_p == IPPROTO_UDP) - lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src, - ud->uh_dport, ud->uh_sport, - IPPROTO_UDP, 0); - else if (ip->ip_p == IPPROTO_TCP) - lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src, - tc->th_dport, tc->th_sport, - IPPROTO_TCP, 0); - else if (ip->ip_p == IPPROTO_ICMP) { - if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) - lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); - else - lnk = NULL; - } else - lnk = NULL; - - if (lnk != NULL) { - if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) { - int accumulate, accumulate2; - struct in_addr original_address; - u_short original_port; - - original_address = GetOriginalAddress(lnk); - original_port = GetOriginalPort(lnk); - -/* Adjust ICMP checksum */ - accumulate = twowords(&ip->ip_src); - accumulate -= twowords(&original_address); - accumulate += ud->uh_sport; - accumulate -= original_port; - accumulate2 = accumulate; - accumulate2 += ip->ip_sum; - ADJUST_CHECKSUM(accumulate, ip->ip_sum); - accumulate2 -= ip->ip_sum; - ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum); - -/* Un-alias address in IP header */ - DifferentialChecksum(&pip->ip_sum, - &original_address, &pip->ip_dst, 2); - pip->ip_dst = original_address; - -/* Un-alias address and port number of original IP packet -fragment contained in ICMP data section */ - ip->ip_src = original_address; - ud->uh_sport = original_port; - } else if (ip->ip_p == IPPROTO_ICMP) { - int accumulate, accumulate2; - struct in_addr original_address; - u_short original_id; - - original_address = GetOriginalAddress(lnk); - original_id = GetOriginalPort(lnk); - -/* Adjust ICMP checksum */ - accumulate = twowords(&ip->ip_src); - accumulate -= twowords(&original_address); - accumulate += ic2->icmp_id; - accumulate -= original_id; - accumulate2 = accumulate; - accumulate2 += ip->ip_sum; - ADJUST_CHECKSUM(accumulate, ip->ip_sum); - accumulate2 -= ip->ip_sum; - ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum); - -/* Un-alias address in IP header */ - DifferentialChecksum(&pip->ip_sum, - &original_address, &pip->ip_dst, 2); - pip->ip_dst = original_address; - -/* Un-alias address of original IP packet and sequence number of - embedded ICMP datagram */ - ip->ip_src = original_address; - ic2->icmp_id = original_id; - } - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - - -static int -IcmpAliasIn(struct libalias *la, struct ip *pip) -{ - int iresult; - struct icmp *ic; - -/* Return if proxy-only mode is enabled */ - if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) - return (PKT_ALIAS_OK); - - ic = (struct icmp *)ip_next(pip); - - iresult = PKT_ALIAS_IGNORED; - switch (ic->icmp_type) { - case ICMP_ECHOREPLY: - case ICMP_TSTAMPREPLY: - if (ic->icmp_code == 0) { - iresult = IcmpAliasIn1(la, pip); - } - break; - case ICMP_UNREACH: - case ICMP_SOURCEQUENCH: - case ICMP_TIMXCEED: - case ICMP_PARAMPROB: - iresult = IcmpAliasIn2(la, pip); - break; - case ICMP_ECHO: - case ICMP_TSTAMP: - iresult = IcmpAliasIn1(la, pip); - break; - } - return (iresult); -} - - -static int -IcmpAliasOut1(struct libalias *la, struct ip *pip, int create) -{ -/* - Alias outgoing echo and timestamp requests. - De-alias outgoing echo and timestamp replies. -*/ - struct alias_link *lnk; - struct icmp *ic; - - ic = (struct icmp *)ip_next(pip); - -/* Save overwritten data for when echo packet returns */ - lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create); - if (lnk != NULL) { - u_short alias_id; - int accumulate; - - alias_id = GetAliasPort(lnk); - -/* Since data field is being modified, adjust ICMP checksum */ - accumulate = ic->icmp_id; - accumulate -= alias_id; - ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); - -/* Alias sequence number */ - ic->icmp_id = alias_id; - -/* Change source address */ - { - struct in_addr alias_address; - - alias_address = GetAliasAddress(lnk); - DifferentialChecksum(&pip->ip_sum, - &alias_address, &pip->ip_src, 2); - pip->ip_src = alias_address; - } - - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - - -static int -IcmpAliasOut2(struct libalias *la, struct ip *pip) -{ -/* - Alias outgoing ICMP error messages containing - IP header and first 64 bits of datagram. -*/ - struct ip *ip; - struct icmp *ic, *ic2; - struct udphdr *ud; - struct tcphdr *tc; - struct alias_link *lnk; - - ic = (struct icmp *)ip_next(pip); - ip = &ic->icmp_ip; - - ud = (struct udphdr *)ip_next(ip); - tc = (struct tcphdr *)ip_next(ip); - ic2 = (struct icmp *)ip_next(ip); - - if (ip->ip_p == IPPROTO_UDP) - lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src, - ud->uh_dport, ud->uh_sport, - IPPROTO_UDP, 0); - else if (ip->ip_p == IPPROTO_TCP) - lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src, - tc->th_dport, tc->th_sport, - IPPROTO_TCP, 0); - else if (ip->ip_p == IPPROTO_ICMP) { - if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) - lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0); - else - lnk = NULL; - } else - lnk = NULL; - - if (lnk != NULL) { - if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) { - int accumulate; - struct in_addr alias_address; - u_short alias_port; - - alias_address = GetAliasAddress(lnk); - alias_port = GetAliasPort(lnk); - -/* Adjust ICMP checksum */ - accumulate = twowords(&ip->ip_dst); - accumulate -= twowords(&alias_address); - accumulate += ud->uh_dport; - accumulate -= alias_port; - ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); - -/* - * Alias address in IP header if it comes from the host - * the original TCP/UDP packet was destined for. - */ - if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { - DifferentialChecksum(&pip->ip_sum, - &alias_address, &pip->ip_src, 2); - pip->ip_src = alias_address; - } -/* Alias address and port number of original IP packet -fragment contained in ICMP data section */ - ip->ip_dst = alias_address; - ud->uh_dport = alias_port; - } else if (ip->ip_p == IPPROTO_ICMP) { - int accumulate; - struct in_addr alias_address; - u_short alias_id; - - alias_address = GetAliasAddress(lnk); - alias_id = GetAliasPort(lnk); - -/* Adjust ICMP checksum */ - accumulate = twowords(&ip->ip_dst); - accumulate -= twowords(&alias_address); - accumulate += ic2->icmp_id; - accumulate -= alias_id; - ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); - -/* - * Alias address in IP header if it comes from the host - * the original ICMP message was destined for. - */ - if (pip->ip_src.s_addr == ip->ip_dst.s_addr) { - DifferentialChecksum(&pip->ip_sum, - &alias_address, &pip->ip_src, 2); - pip->ip_src = alias_address; - } -/* Alias address of original IP packet and sequence number of - embedded ICMP datagram */ - ip->ip_dst = alias_address; - ic2->icmp_id = alias_id; - } - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - - -static int -IcmpAliasOut(struct libalias *la, struct ip *pip, int create) -{ - int iresult; - struct icmp *ic; - - (void)create; - -/* Return if proxy-only mode is enabled */ - if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) - return (PKT_ALIAS_OK); - - ic = (struct icmp *)ip_next(pip); - - iresult = PKT_ALIAS_IGNORED; - switch (ic->icmp_type) { - case ICMP_ECHO: - case ICMP_TSTAMP: - if (ic->icmp_code == 0) { - iresult = IcmpAliasOut1(la, pip, create); - } - break; - case ICMP_UNREACH: - case ICMP_SOURCEQUENCH: - case ICMP_TIMXCEED: - case ICMP_PARAMPROB: - iresult = IcmpAliasOut2(la, pip); - break; - case ICMP_ECHOREPLY: - case ICMP_TSTAMPREPLY: - iresult = IcmpAliasOut1(la, pip, create); - } - return (iresult); -} - - - -static int -ProtoAliasIn(struct libalias *la, struct ip *pip) -{ -/* - Handle incoming IP packets. The - only thing which is done in this case is to alias - the dest IP address of the packet to our inside - machine. -*/ - struct alias_link *lnk; - -/* Return if proxy-only mode is enabled */ - if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) - return (PKT_ALIAS_OK); - - lnk = FindProtoIn(la, pip->ip_src, pip->ip_dst, pip->ip_p); - if (lnk != NULL) { - struct in_addr original_address; - - original_address = GetOriginalAddress(lnk); - -/* Restore original IP address */ - DifferentialChecksum(&pip->ip_sum, - &original_address, &pip->ip_dst, 2); - pip->ip_dst = original_address; - - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - - -static int -ProtoAliasOut(struct libalias *la, struct ip *pip, int create) -{ -/* - Handle outgoing IP packets. The - only thing which is done in this case is to alias - the source IP address of the packet. -*/ - struct alias_link *lnk; - - (void)create; - -/* Return if proxy-only mode is enabled */ - if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) - return (PKT_ALIAS_OK); - - lnk = FindProtoOut(la, pip->ip_src, pip->ip_dst, pip->ip_p); - if (lnk != NULL) { - struct in_addr alias_address; - - alias_address = GetAliasAddress(lnk); - -/* Change source address */ - DifferentialChecksum(&pip->ip_sum, - &alias_address, &pip->ip_src, 2); - pip->ip_src = alias_address; - - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - - -static int -UdpAliasIn(struct libalias *la, struct ip *pip) -{ - struct udphdr *ud; - struct alias_link *lnk; - -/* Return if proxy-only mode is enabled */ - if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) - return (PKT_ALIAS_OK); - - ud = (struct udphdr *)ip_next(pip); - - lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, - ud->uh_sport, ud->uh_dport, - IPPROTO_UDP, 1); - if (lnk != NULL) { - struct in_addr alias_address; - struct in_addr original_address; - u_short alias_port; - int accumulate; - int r = 0; - - alias_address = GetAliasAddress(lnk); - original_address = GetOriginalAddress(lnk); - alias_port = ud->uh_dport; - ud->uh_dport = GetOriginalPort(lnk); - -/* Special processing for IP encoding protocols */ - if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) - AliasHandleCUSeeMeIn(la, pip, original_address); -/* If NETBIOS Datagram, It should be alias address in UDP Data, too */ - else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER - || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) - r = AliasHandleUdpNbt(la, pip, lnk, &original_address, ud->uh_dport); - else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER - || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) - r = AliasHandleUdpNbtNS(la, pip, lnk, &alias_address, &alias_port, - &original_address, &ud->uh_dport); - -/* If UDP checksum is not zero, then adjust since destination port */ -/* is being unaliased and destination address is being altered. */ - if (ud->uh_sum != 0) { - accumulate = alias_port; - accumulate -= ud->uh_dport; - accumulate += twowords(&alias_address); - accumulate -= twowords(&original_address); - ADJUST_CHECKSUM(accumulate, ud->uh_sum); - } -/* Restore original IP address */ - DifferentialChecksum(&pip->ip_sum, - &original_address, &pip->ip_dst, 2); - pip->ip_dst = original_address; - - /* - * If we cannot figure out the packet, ignore it. - */ - if (r < 0) - return (PKT_ALIAS_IGNORED); - else - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - -static int -UdpAliasOut(struct libalias *la, struct ip *pip, int create) -{ - struct udphdr *ud; - struct alias_link *lnk; - -/* Return if proxy-only mode is enabled */ - if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) - return (PKT_ALIAS_OK); - - ud = (struct udphdr *)ip_next(pip); - - lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, - ud->uh_sport, ud->uh_dport, - IPPROTO_UDP, create); - if (lnk != NULL) { - u_short alias_port; - struct in_addr alias_address; - - alias_address = GetAliasAddress(lnk); - alias_port = GetAliasPort(lnk); - -/* Special processing for IP encoding protocols */ - if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) - AliasHandleCUSeeMeOut(la, pip, lnk); -/* If NETBIOS Datagram, It should be alias address in UDP Data, too */ - else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER - || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER) - AliasHandleUdpNbt(la, pip, lnk, &alias_address, alias_port); - else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER - || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER) - AliasHandleUdpNbtNS(la, pip, lnk, &pip->ip_src, &ud->uh_sport, - &alias_address, &alias_port); -/* - * We don't know in advance what TID the TFTP server will choose, - * so we create a wilcard link (destination port is unspecified) - * that will match any TID from a given destination. - */ - else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER) - FindRtspOut(la, pip->ip_src, pip->ip_dst, - ud->uh_sport, alias_port, IPPROTO_UDP); - -/* If UDP checksum is not zero, adjust since source port is */ -/* being aliased and source address is being altered */ - if (ud->uh_sum != 0) { - int accumulate; - - accumulate = ud->uh_sport; - accumulate -= alias_port; - accumulate += twowords(&pip->ip_src); - accumulate -= twowords(&alias_address); - ADJUST_CHECKSUM(accumulate, ud->uh_sum); - } -/* Put alias port in UDP header */ - ud->uh_sport = alias_port; - -/* Change source address */ - DifferentialChecksum(&pip->ip_sum, - &alias_address, &pip->ip_src, 2); - pip->ip_src = alias_address; - - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - - - -static int -TcpAliasIn(struct libalias *la, struct ip *pip) -{ - struct tcphdr *tc; - struct alias_link *lnk; - - tc = (struct tcphdr *)ip_next(pip); - - lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, - tc->th_sport, tc->th_dport, - IPPROTO_TCP, - !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)); - if (lnk != NULL) { - struct in_addr alias_address; - struct in_addr original_address; - struct in_addr proxy_address; - u_short alias_port; - u_short proxy_port; - int accumulate; - -/* Special processing for IP encoding protocols */ - if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER - || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) - AliasHandlePptpIn(la, pip, lnk); - else if (la->skinnyPort != 0 && (ntohs(tc->th_dport) == la->skinnyPort - || ntohs(tc->th_sport) == la->skinnyPort)) - AliasHandleSkinny(la, pip, lnk); - - alias_address = GetAliasAddress(lnk); - original_address = GetOriginalAddress(lnk); - proxy_address = GetProxyAddress(lnk); - alias_port = tc->th_dport; - tc->th_dport = GetOriginalPort(lnk); - proxy_port = GetProxyPort(lnk); - -/* Adjust TCP checksum since destination port is being unaliased */ -/* and destination port is being altered. */ - accumulate = alias_port; - accumulate -= tc->th_dport; - accumulate += twowords(&alias_address); - accumulate -= twowords(&original_address); - -/* If this is a proxy, then modify the TCP source port and - checksum accumulation */ - if (proxy_port != 0) { - accumulate += tc->th_sport; - tc->th_sport = proxy_port; - accumulate -= tc->th_sport; - accumulate += twowords(&pip->ip_src); - accumulate -= twowords(&proxy_address); - } -/* See if ACK number needs to be modified */ - if (GetAckModified(lnk) == 1) { - int delta; - - delta = GetDeltaAckIn(pip, lnk); - if (delta != 0) { - accumulate += twowords(&tc->th_ack); - tc->th_ack = htonl(ntohl(tc->th_ack) - delta); - accumulate -= twowords(&tc->th_ack); - } - } - ADJUST_CHECKSUM(accumulate, tc->th_sum); - -/* Restore original IP address */ - accumulate = twowords(&pip->ip_dst); - pip->ip_dst = original_address; - accumulate -= twowords(&pip->ip_dst); - -/* If this is a transparent proxy packet, then modify the source - address */ - if (proxy_address.s_addr != 0) { - accumulate += twowords(&pip->ip_src); - pip->ip_src = proxy_address; - accumulate -= twowords(&pip->ip_src); - } - ADJUST_CHECKSUM(accumulate, pip->ip_sum); - -/* Monitor TCP connection state */ - TcpMonitorIn(pip, lnk); - - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - -static int -TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) -{ - int proxy_type; - u_short dest_port; - u_short proxy_server_port; - struct in_addr dest_address; - struct in_addr proxy_server_address; - struct tcphdr *tc; - struct alias_link *lnk; - - tc = (struct tcphdr *)ip_next(pip); - - proxy_type = ProxyCheck(la, pip, &proxy_server_address, &proxy_server_port); - - if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) - return (PKT_ALIAS_OK); - -/* If this is a transparent proxy, save original destination, - then alter the destination and adjust checksums */ - dest_port = tc->th_dport; - dest_address = pip->ip_dst; - if (proxy_type != 0) { - int accumulate; - - accumulate = tc->th_dport; - tc->th_dport = proxy_server_port; - accumulate -= tc->th_dport; - accumulate += twowords(&pip->ip_dst); - accumulate -= twowords(&proxy_server_address); - ADJUST_CHECKSUM(accumulate, tc->th_sum); - - accumulate = twowords(&pip->ip_dst); - pip->ip_dst = proxy_server_address; - accumulate -= twowords(&pip->ip_dst); - ADJUST_CHECKSUM(accumulate, pip->ip_sum); - } - lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst, - tc->th_sport, tc->th_dport, - IPPROTO_TCP, create); - if (lnk == NULL) - return (PKT_ALIAS_IGNORED); - if (lnk != NULL) { - u_short alias_port; - struct in_addr alias_address; - int accumulate; - -/* Save original destination address, if this is a proxy packet. - Also modify packet to include destination encoding. This may - change the size of IP header. */ - if (proxy_type != 0) { - SetProxyPort(lnk, dest_port); - SetProxyAddress(lnk, dest_address); - ProxyModify(la, lnk, pip, maxpacketsize, proxy_type); - tc = (struct tcphdr *)ip_next(pip); - } -/* Get alias address and port */ - alias_port = GetAliasPort(lnk); - alias_address = GetAliasAddress(lnk); - -/* Monitor TCP connection state */ - TcpMonitorOut(pip, lnk); - -/* Special processing for IP encoding protocols */ - if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER - || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) - AliasHandleFtpOut(la, pip, lnk, maxpacketsize); - else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 - || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) - AliasHandleIrcOut(la, pip, lnk, maxpacketsize); - else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1 - || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1 - || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2 - || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) - AliasHandleRtspOut(la, pip, lnk, maxpacketsize); - else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER - || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER) - AliasHandlePptpOut(la, pip, lnk); - else if (la->skinnyPort != 0 && (ntohs(tc->th_sport) == la->skinnyPort - || ntohs(tc->th_dport) == la->skinnyPort)) - AliasHandleSkinny(la, pip, lnk); - -/* Adjust TCP checksum since source port is being aliased */ -/* and source address is being altered */ - accumulate = tc->th_sport; - tc->th_sport = alias_port; - accumulate -= tc->th_sport; - accumulate += twowords(&pip->ip_src); - accumulate -= twowords(&alias_address); - -/* Modify sequence number if necessary */ - if (GetAckModified(lnk) == 1) { - int delta; - - delta = GetDeltaSeqOut(pip, lnk); - if (delta != 0) { - accumulate += twowords(&tc->th_seq); - tc->th_seq = htonl(ntohl(tc->th_seq) + delta); - accumulate -= twowords(&tc->th_seq); - } - } - ADJUST_CHECKSUM(accumulate, tc->th_sum); - -/* Change source address */ - accumulate = twowords(&pip->ip_src); - pip->ip_src = alias_address; - accumulate -= twowords(&pip->ip_src); - ADJUST_CHECKSUM(accumulate, pip->ip_sum); - - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_IGNORED); -} - - - - -/* Fragment Handling - - FragmentIn() - FragmentOut() - -The packet aliasing module has a limited ability for handling IP -fragments. If the ICMP, TCP or UDP header is in the first fragment -received, then the ID number of the IP packet is saved, and other -fragments are identified according to their ID number and IP address -they were sent from. Pointers to unresolved fragments can also be -saved and recalled when a header fragment is seen. -*/ - -/* Local prototypes */ -static int FragmentIn(struct libalias *, struct ip *); -static int FragmentOut(struct libalias *, struct ip *); - - -static int -FragmentIn(struct libalias *la, struct ip *pip) -{ - struct alias_link *lnk; - - lnk = FindFragmentIn2(la, pip->ip_src, pip->ip_dst, pip->ip_id); - if (lnk != NULL) { - struct in_addr original_address; - - GetFragmentAddr(lnk, &original_address); - DifferentialChecksum(&pip->ip_sum, - &original_address, &pip->ip_dst, 2); - pip->ip_dst = original_address; - - return (PKT_ALIAS_OK); - } - return (PKT_ALIAS_UNRESOLVED_FRAGMENT); -} - - -static int -FragmentOut(struct libalias *la, struct ip *pip) -{ - struct in_addr alias_address; - - alias_address = FindAliasAddress(la, pip->ip_src); - DifferentialChecksum(&pip->ip_sum, - &alias_address, &pip->ip_src, 2); - pip->ip_src = alias_address; - - return (PKT_ALIAS_OK); -} - - - - - - -/* Outside World Access - - PacketAliasSaveFragment() - PacketAliasGetFragment() - PacketAliasFragmentIn() - PacketAliasIn() - PacketAliasOut() - PacketUnaliasOut() - -(prototypes in alias.h) -*/ - - -int -LibAliasSaveFragment(struct libalias *la, char *ptr) -{ - int iresult; - struct alias_link *lnk; - struct ip *pip; - - pip = (struct ip *)ptr; - lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id); - iresult = PKT_ALIAS_ERROR; - if (lnk != NULL) { - SetFragmentPtr(lnk, ptr); - iresult = PKT_ALIAS_OK; - } - return (iresult); -} - - -char * -LibAliasGetFragment(struct libalias *la, char *ptr) -{ - struct alias_link *lnk; - char *fptr; - struct ip *pip; - - pip = (struct ip *)ptr; - lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id); - if (lnk != NULL) { - GetFragmentPtr(lnk, &fptr); - SetFragmentPtr(lnk, NULL); - SetExpire(lnk, 0); /* Deletes link */ - - return (fptr); - } else { - return (NULL); - } -} - - -void -LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly - * de-aliased header - * fragment */ - char *ptr_fragment /* Points to fragment which must be - * de-aliased */ -) -{ - struct ip *pip; - struct ip *fpip; - - (void)la; - pip = (struct ip *)ptr; - fpip = (struct ip *)ptr_fragment; - - DifferentialChecksum(&fpip->ip_sum, - &pip->ip_dst, &fpip->ip_dst, 2); - fpip->ip_dst = pip->ip_dst; -} - - -int -LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) -{ - struct in_addr alias_addr; - struct ip *pip; - int iresult; - - if (la->packetAliasMode & PKT_ALIAS_REVERSE) { - la->packetAliasMode &= ~PKT_ALIAS_REVERSE; - iresult = LibAliasOut(la, ptr, maxpacketsize); - la->packetAliasMode |= PKT_ALIAS_REVERSE; - return (iresult); - } - HouseKeeping(la); - ClearCheckNewLink(la); - pip = (struct ip *)ptr; - alias_addr = pip->ip_dst; - - /* Defense against mangled packets */ - if (ntohs(pip->ip_len) > maxpacketsize - || (pip->ip_hl << 2) > maxpacketsize) - return (PKT_ALIAS_IGNORED); - - iresult = PKT_ALIAS_IGNORED; - if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { - switch (pip->ip_p) { - case IPPROTO_ICMP: - iresult = IcmpAliasIn(la, pip); - break; - case IPPROTO_UDP: - iresult = UdpAliasIn(la, pip); - break; - case IPPROTO_TCP: - iresult = TcpAliasIn(la, pip); - break; - case IPPROTO_GRE: - if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY || - AliasHandlePptpGreIn(la, pip) == 0) - iresult = PKT_ALIAS_OK; - else - iresult = ProtoAliasIn(la, pip); - break; - default: - iresult = ProtoAliasIn(la, pip); - break; - } - - if (ntohs(pip->ip_off) & IP_MF) { - struct alias_link *lnk; - - lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); - if (lnk != NULL) { - iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; - SetFragmentAddr(lnk, pip->ip_dst); - } else { - iresult = PKT_ALIAS_ERROR; - } - } - } else { - iresult = FragmentIn(la, pip); - } - - return (iresult); -} - - - -/* Unregistered address ranges */ - -/* 10.0.0.0 -> 10.255.255.255 */ -#define UNREG_ADDR_A_LOWER 0x0a000000 -#define UNREG_ADDR_A_UPPER 0x0affffff - -/* 172.16.0.0 -> 172.31.255.255 */ -#define UNREG_ADDR_B_LOWER 0xac100000 -#define UNREG_ADDR_B_UPPER 0xac1fffff - -/* 192.168.0.0 -> 192.168.255.255 */ -#define UNREG_ADDR_C_LOWER 0xc0a80000 -#define UNREG_ADDR_C_UPPER 0xc0a8ffff - -int -LibAliasOut(struct libalias *la, char *ptr, /* valid IP packet */ - int maxpacketsize /* How much the packet data may grow (FTP - * and IRC inline changes) */ -) -{ - return (LibAliasOutTry(la, ptr, maxpacketsize, 1)); -} - -int -LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */ - int maxpacketsize, /* How much the packet data may grow (FTP - * and IRC inline changes) */ - int create /* Create new entries ? */ -) -{ - int iresult; - struct in_addr addr_save; - struct ip *pip; - - if (la->packetAliasMode & PKT_ALIAS_REVERSE) { - la->packetAliasMode &= ~PKT_ALIAS_REVERSE; - iresult = LibAliasIn(la, ptr, maxpacketsize); - la->packetAliasMode |= PKT_ALIAS_REVERSE; - return (iresult); - } - HouseKeeping(la); - ClearCheckNewLink(la); - pip = (struct ip *)ptr; - - /* Defense against mangled packets */ - if (ntohs(pip->ip_len) > maxpacketsize - || (pip->ip_hl << 2) > maxpacketsize) - return (PKT_ALIAS_IGNORED); - - addr_save = GetDefaultAliasAddress(la); - if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) { - u_long addr; - int iclass; - - iclass = 0; - addr = ntohl(pip->ip_src.s_addr); - if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) - iclass = 3; - else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) - iclass = 2; - else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) - iclass = 1; - - if (iclass == 0) { - SetDefaultAliasAddress(la, pip->ip_src); - } - } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { - SetDefaultAliasAddress(la, pip->ip_src); - } - iresult = PKT_ALIAS_IGNORED; - if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { - switch (pip->ip_p) { - case IPPROTO_ICMP: - iresult = IcmpAliasOut(la, pip, create); - break; - case IPPROTO_UDP: - iresult = UdpAliasOut(la, pip, create); - break; - case IPPROTO_TCP: - iresult = TcpAliasOut(la, pip, maxpacketsize, create); - break; - case IPPROTO_GRE: - if (AliasHandlePptpGreOut(la, pip) == 0) - iresult = PKT_ALIAS_OK; - else - iresult = ProtoAliasOut(la, pip, create); - break; - default: - iresult = ProtoAliasOut(la, pip, create); - break; - } - } else { - iresult = FragmentOut(la, pip); - } - - SetDefaultAliasAddress(la, addr_save); - return (iresult); -} - -int -LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */ - int maxpacketsize /* for error checking */ -) -{ - struct ip *pip; - struct icmp *ic; - struct udphdr *ud; - struct tcphdr *tc; - struct alias_link *lnk; - int iresult = PKT_ALIAS_IGNORED; - - pip = (struct ip *)ptr; - - /* Defense against mangled packets */ - if (ntohs(pip->ip_len) > maxpacketsize - || (pip->ip_hl << 2) > maxpacketsize) - return (iresult); - - ud = (struct udphdr *)ip_next(pip); - tc = (struct tcphdr *)ip_next(pip); - ic = (struct icmp *)ip_next(pip); - - /* Find a link */ - if (pip->ip_p == IPPROTO_UDP) - lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, - ud->uh_dport, ud->uh_sport, - IPPROTO_UDP, 0); - else if (pip->ip_p == IPPROTO_TCP) - lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src, - tc->th_dport, tc->th_sport, - IPPROTO_TCP, 0); - else if (pip->ip_p == IPPROTO_ICMP) - lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0); - else - lnk = NULL; - - /* Change it from an aliased packet to an unaliased packet */ - if (lnk != NULL) { - if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) { - int accumulate; - struct in_addr original_address; - u_short original_port; - - original_address = GetOriginalAddress(lnk); - original_port = GetOriginalPort(lnk); - - /* Adjust TCP/UDP checksum */ - accumulate = twowords(&pip->ip_src); - accumulate -= twowords(&original_address); - - if (pip->ip_p == IPPROTO_UDP) { - accumulate += ud->uh_sport; - accumulate -= original_port; - ADJUST_CHECKSUM(accumulate, ud->uh_sum); - } else { - accumulate += tc->th_sport; - accumulate -= original_port; - ADJUST_CHECKSUM(accumulate, tc->th_sum); - } - - /* Adjust IP checksum */ - DifferentialChecksum(&pip->ip_sum, - &original_address, &pip->ip_src, 2); - - /* Un-alias source address and port number */ - pip->ip_src = original_address; - if (pip->ip_p == IPPROTO_UDP) - ud->uh_sport = original_port; - else - tc->th_sport = original_port; - - iresult = PKT_ALIAS_OK; - - } else if (pip->ip_p == IPPROTO_ICMP) { - - int accumulate; - struct in_addr original_address; - u_short original_id; - - original_address = GetOriginalAddress(lnk); - original_id = GetOriginalPort(lnk); - - /* Adjust ICMP checksum */ - accumulate = twowords(&pip->ip_src); - accumulate -= twowords(&original_address); - accumulate += ic->icmp_id; - accumulate -= original_id; - ADJUST_CHECKSUM(accumulate, ic->icmp_cksum); - - /* Adjust IP checksum */ - DifferentialChecksum(&pip->ip_sum, - &original_address, &pip->ip_src, 2); - - /* Un-alias source address and port number */ - pip->ip_src = original_address; - ic->icmp_id = original_id; - - iresult = PKT_ALIAS_OK; - } - } - return (iresult); - -} diff --git a/lib/libalias/alias.h b/lib/libalias/alias.h deleted file mode 100644 index 1deec9f08315..000000000000 --- a/lib/libalias/alias.h +++ /dev/null @@ -1,265 +0,0 @@ -/* lint -save -library Flexelint comment for external headers */ - -/*- - * Copyright (c) 2001 Charles Mott - * 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 */ diff --git a/lib/libalias/alias_cuseeme.c b/lib/libalias/alias_cuseeme.c deleted file mode 100644 index cbacc55cad8d..000000000000 --- a/lib/libalias/alias_cuseeme.c +++ /dev/null @@ -1,123 +0,0 @@ -/*- - * Copyright (c) 1998 Brian Somers - * with the aid of code written by - * Junichi SATOH 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#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; - } - } -} diff --git a/lib/libalias/alias_db.c b/lib/libalias/alias_db.c deleted file mode 100644 index f9c953b27b1f..000000000000 --- a/lib/libalias/alias_db.c +++ /dev/null @@ -1,2788 +0,0 @@ -/*- - * Copyright (c) 2001 Charles Mott - * 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 -__FBSDID("$FreeBSD$"); - -/* - Alias_db.c encapsulates all data structures used for storing - packet aliasing data. Other parts of the aliasing software - access data through functions provided in this file. - - Data storage is based on the notion of a "link", which is - established for ICMP echo/reply packets, UDP datagrams and - TCP stream connections. A link stores the original source - and destination addresses. For UDP and TCP, it also stores - source and destination port numbers, as well as an alias - port number. Links are also used to store information about - fragments. - - There is a facility for sweeping through and deleting old - links as new packets are sent through. A simple timeout is - used for ICMP and UDP links. TCP links are left alone unless - there is an incomplete connection, in which case the link - can be deleted after a certain amount of time. - - - Initial version: August, 1996 (cjm) - - Version 1.4: September 16, 1996 (cjm) - Facility for handling incoming links added. - - Version 1.6: September 18, 1996 (cjm) - ICMP data handling simplified. - - Version 1.7: January 9, 1997 (cjm) - Fragment handling simplified. - Saves pointers for unresolved fragments. - Permits links for unspecified remote ports - or unspecified remote addresses. - Fixed bug which did not properly zero port - table entries after a link was deleted. - Cleaned up some obsolete comments. - - Version 1.8: January 14, 1997 (cjm) - Fixed data type error in StartPoint(). - (This error did not exist prior to v1.7 - and was discovered and fixed by Ari Suutari) - - Version 1.9: February 1, 1997 - Optionally, connections initiated from packet aliasing host - machine will will not have their port number aliased unless it - conflicts with an aliasing port already being used. (cjm) - - All options earlier being #ifdef'ed are now available through - a new interface, SetPacketAliasMode(). This allows run time - control (which is now available in PPP+pktAlias through the - 'alias' keyword). (ee) - - Added ability to create an alias port without - either destination address or port specified. - port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee) - - Removed K&R style function headers - and general cleanup. (ee) - - Added packetAliasMode to replace compiler #defines's (ee) - - Allocates sockets for partially specified - ports if ALIAS_USE_SOCKETS defined. (cjm) - - Version 2.0: March, 1997 - SetAliasAddress() will now clean up alias links - if the aliasing address is changed. (cjm) - - PacketAliasPermanentLink() function added to support permanent - links. (J. Fortes suggested the need for this.) - Examples: - - (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port - - (192.168.0.2, port 21) <-> alias port 3604, known dest addr - unknown dest port - - These permanent links allow for incoming connections to - machines on the local network. They can be given with a - user-chosen amount of specificity, with increasing specificity - meaning more security. (cjm) - - Quite a bit of rework to the basic engine. The portTable[] - array, which kept track of which ports were in use was replaced - by a table/linked list structure. (cjm) - - SetExpire() function added. (cjm) - - DeleteLink() no longer frees memory association with a pointer - to a fragment (this bug was first recognized by E. Eklund in - v1.9). - - Version 2.1: May, 1997 (cjm) - Packet aliasing engine reworked so that it can handle - multiple external addresses rather than just a single - host address. - - PacketAliasRedirectPort() and PacketAliasRedirectAddr() - added to the API. The first function is a more generalized - version of PacketAliasPermanentLink(). The second function - implements static network address translation. - - Version 3.2: July, 2000 (salander and satoh) - Added FindNewPortGroup to get contiguous range of port values. - - Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing - link but not actually add one. - - Added FindRtspOut, which is closely derived from FindUdpTcpOut, - except that the alias port (from FindNewPortGroup) is provided - as input. - - See HISTORY file for additional revisions. -*/ - - -/* System include files */ -#include -#include -#include -#include - -#include -#include -#include -#include - -/* BSD network include files */ -#include -#include -#include -#include -#include - -#include "alias.h" -#include "alias_local.h" - - -static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead); - - -/* - Constants (note: constants are also defined - near relevant functions or structs) -*/ - -/* Parameters used for cleanup of expired links */ -#define ALIAS_CLEANUP_INTERVAL_SECS 60 -#define ALIAS_CLEANUP_MAX_SPOKES 30 - -/* Timeouts (in seconds) for different link types */ -#define ICMP_EXPIRE_TIME 60 -#define UDP_EXPIRE_TIME 60 -#define PROTO_EXPIRE_TIME 60 -#define FRAGMENT_ID_EXPIRE_TIME 10 -#define FRAGMENT_PTR_EXPIRE_TIME 30 - -/* TCP link expire time for different cases */ -/* When the link has been used and closed - minimal grace time to - allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */ -#ifndef TCP_EXPIRE_DEAD -#define TCP_EXPIRE_DEAD 10 -#endif - -/* When the link has been used and closed on one side - the other side - is allowed to still send data */ -#ifndef TCP_EXPIRE_SINGLEDEAD -#define TCP_EXPIRE_SINGLEDEAD 90 -#endif - -/* When the link isn't yet up */ -#ifndef TCP_EXPIRE_INITIAL -#define TCP_EXPIRE_INITIAL 300 -#endif - -/* When the link is up */ -#ifndef TCP_EXPIRE_CONNECTED -#define TCP_EXPIRE_CONNECTED 86400 -#endif - - -/* Dummy port number codes used for FindLinkIn/Out() and AddLink(). - These constants can be anything except zero, which indicates an - unknown port number. */ - -#define NO_DEST_PORT 1 -#define NO_SRC_PORT 1 - - - -/* Data Structures - - The fundamental data structure used in this program is - "struct alias_link". Whenever a TCP connection is made, - a UDP datagram is sent out, or an ICMP echo request is made, - a link record is made (if it has not already been created). - The link record is identified by the source address/port - and the destination address/port. In the case of an ICMP - echo request, the source port is treated as being equivalent - with the 16-bit ID number of the ICMP packet. - - The link record also can store some auxiliary data. For - TCP connections that have had sequence and acknowledgment - modifications, data space is available to track these changes. - A state field is used to keep track in changes to the TCP - connection state. ID numbers of fragments can also be - stored in the auxiliary space. Pointers to unresolved - fragments can also be stored. - - The link records support two independent chainings. Lookup - tables for input and out tables hold the initial pointers - the link chains. On input, the lookup table indexes on alias - port and link type. On output, the lookup table indexes on - source address, destination address, source port, destination - port and link type. -*/ - -struct ack_data_record { /* used to save changes to ACK/sequence - * numbers */ - u_long ack_old; - u_long ack_new; - int delta; - int active; -}; - -struct tcp_state { /* Information about TCP connection */ - int in; /* State for outside -> inside */ - int out; /* State for inside -> outside */ - int index; /* Index to ACK data array */ - int ack_modified; /* Indicates whether ACK and - * sequence numbers */ - /* been modified */ -}; - -#define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes - * saved for a modified TCP stream */ -struct tcp_dat { - struct tcp_state state; - struct ack_data_record ack[N_LINK_TCP_DATA]; - int fwhole; /* Which firewall record is used for this - * hole? */ -}; - -struct server { /* LSNAT server pool (circular list) */ - struct in_addr addr; - u_short port; - struct server *next; -}; - -struct alias_link { /* Main data structure */ - struct libalias *la; - struct in_addr src_addr; /* Address and port information */ - struct in_addr dst_addr; - struct in_addr alias_addr; - struct in_addr proxy_addr; - u_short src_port; - u_short dst_port; - u_short alias_port; - u_short proxy_port; - struct server *server; - - int link_type; /* Type of link: TCP, UDP, ICMP, - * proto, frag */ - -/* values for link_type */ -#define LINK_ICMP IPPROTO_ICMP -#define LINK_UDP IPPROTO_UDP -#define LINK_TCP IPPROTO_TCP -#define LINK_FRAGMENT_ID (IPPROTO_MAX + 1) -#define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2) -#define LINK_ADDR (IPPROTO_MAX + 3) -#define LINK_PPTP (IPPROTO_MAX + 4) - - int flags; /* indicates special characteristics */ - int pflags; /* protocol-specific flags */ - -/* flag bits */ -#define LINK_UNKNOWN_DEST_PORT 0x01 -#define LINK_UNKNOWN_DEST_ADDR 0x02 -#define LINK_PERMANENT 0x04 -#define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */ -#define LINK_UNFIREWALLED 0x08 - - int timestamp; /* Time link was last accessed */ - int expire_time; /* Expire time for link */ - - int sockfd; /* socket descriptor */ - - LIST_ENTRY (alias_link) list_out; /* Linked list of - * pointers for */ - LIST_ENTRY (alias_link) list_in; /* input and output - * lookup tables */ - - union { /* Auxiliary data */ - char *frag_ptr; - struct in_addr frag_addr; - struct tcp_dat *tcp; - } data; -}; - -/* Internal utility routines (used only in alias_db.c) - -Lookup table starting points: - StartPointIn() -- link table initial search point for - incoming packets - StartPointOut() -- link table initial search point for - outgoing packets - -Miscellaneous: - SeqDiff() -- difference between two TCP sequences - ShowAliasStats() -- send alias statistics to a monitor file -*/ - - -/* Local prototypes */ -static u_int StartPointIn(struct in_addr, u_short, int); - -static u_int -StartPointOut(struct in_addr, struct in_addr, - u_short, u_short, int); - -static int SeqDiff(u_long, u_long); - -static void ShowAliasStats(struct libalias *); - -#ifndef NO_FW_PUNCH -/* Firewall control */ -static void InitPunchFW(struct libalias *); -static void UninitPunchFW(struct libalias *); -static void ClearFWHole(struct alias_link *); - -#endif - -/* Log file control */ -static void InitPacketAliasLog(struct libalias *); -static void UninitPacketAliasLog(struct libalias *); - -static u_int -StartPointIn(struct in_addr alias_addr, - u_short alias_port, - int link_type) -{ - u_int n; - - n = alias_addr.s_addr; - if (link_type != LINK_PPTP) - n += alias_port; - n += link_type; - return (n % LINK_TABLE_IN_SIZE); -} - - -static u_int -StartPointOut(struct in_addr src_addr, struct in_addr dst_addr, - u_short src_port, u_short dst_port, int link_type) -{ - u_int n; - - n = src_addr.s_addr; - n += dst_addr.s_addr; - if (link_type != LINK_PPTP) { - n += src_port; - n += dst_port; - } - n += link_type; - - return (n % LINK_TABLE_OUT_SIZE); -} - - -static int -SeqDiff(u_long x, u_long y) -{ -/* Return the difference between two TCP sequence numbers */ - -/* - This function is encapsulated in case there are any unusual - arithmetic conditions that need to be considered. -*/ - - return (ntohl(y) - ntohl(x)); -} - - -static void -ShowAliasStats(struct libalias *la) -{ -/* Used for debugging */ - - if (la->monitorFile) { - fprintf(la->monitorFile, - "icmp=%d, udp=%d, tcp=%d, pptp=%d, proto=%d, frag_id=%d frag_ptr=%d", - la->icmpLinkCount, - la->udpLinkCount, - la->tcpLinkCount, - la->pptpLinkCount, - la->protoLinkCount, - la->fragmentIdLinkCount, - la->fragmentPtrLinkCount); - - fprintf(la->monitorFile, " / tot=%d (sock=%d)\n", - la->icmpLinkCount + la->udpLinkCount - + la->tcpLinkCount - + la->pptpLinkCount - + la->protoLinkCount - + la->fragmentIdLinkCount - + la->fragmentPtrLinkCount, - la->sockCount); - - fflush(la->monitorFile); - } -} - - - - - -/* Internal routines for finding, deleting and adding links - -Port Allocation: - GetNewPort() -- find and reserve new alias port number - GetSocket() -- try to allocate a socket for a given port - -Link creation and deletion: - CleanupAliasData() - remove all link chains from lookup table - IncrementalCleanup() - look for stale links in a single chain - DeleteLink() - remove link - AddLink() - add link - ReLink() - change link - -Link search: - FindLinkOut() - find link for outgoing packets - FindLinkIn() - find link for incoming packets - -Port search: - FindNewPortGroup() - find an available group of ports -*/ - -/* Local prototypes */ -static int GetNewPort(struct libalias *, struct alias_link *, int); - -static u_short GetSocket(struct libalias *, u_short, int *, int); - -static void CleanupAliasData(struct libalias *); - -static void IncrementalCleanup(struct libalias *); - -static void DeleteLink(struct alias_link *); - -static struct alias_link * -AddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr, - u_short, u_short, int, int); - -static struct alias_link * -ReLink(struct alias_link *, - struct in_addr, struct in_addr, struct in_addr, - u_short, u_short, int, int); - -static struct alias_link * - FindLinkOut (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); - -static struct alias_link * - FindLinkIn (struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); - - -#define ALIAS_PORT_BASE 0x08000 -#define ALIAS_PORT_MASK 0x07fff -#define ALIAS_PORT_MASK_EVEN 0x07ffe -#define GET_NEW_PORT_MAX_ATTEMPTS 20 - -#define GET_ALIAS_PORT -1 -#define GET_ALIAS_ID GET_ALIAS_PORT - -#define FIND_EVEN_ALIAS_BASE 1 - -/* GetNewPort() allocates port numbers. Note that if a port number - is already in use, that does not mean that it cannot be used by - another link concurrently. This is because GetNewPort() looks for - unused triplets: (dest addr, dest port, alias port). */ - -static int -GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param) -{ - int i; - int max_trials; - u_short port_sys; - u_short port_net; - -/* - Description of alias_port_param for GetNewPort(). When - this parameter is zero or positive, it precisely specifies - the port number. GetNewPort() will return this number - without check that it is in use. - - When this parameter is GET_ALIAS_PORT, it indicates to get a randomly - selected port number. -*/ - - if (alias_port_param == GET_ALIAS_PORT) { - /* - * The aliasing port is automatically selected by one of - * two methods below: - */ - max_trials = GET_NEW_PORT_MAX_ATTEMPTS; - - if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) { - /* - * When the PKT_ALIAS_SAME_PORTS option is chosen, - * the first try will be the actual source port. If - * this is already in use, the remainder of the - * trials will be random. - */ - port_net = lnk->src_port; - port_sys = ntohs(port_net); - } else { - /* First trial and all subsequent are random. */ - port_sys = random() & ALIAS_PORT_MASK; - port_sys += ALIAS_PORT_BASE; - port_net = htons(port_sys); - } - } else if (alias_port_param >= 0 && alias_port_param < 0x10000) { - lnk->alias_port = (u_short) alias_port_param; - return (0); - } else { -#ifdef DEBUG - fprintf(stderr, "PacketAlias/GetNewPort(): "); - fprintf(stderr, "input parameter error\n"); -#endif - return (-1); - } - - -/* Port number search */ - for (i = 0; i < max_trials; i++) { - int go_ahead; - struct alias_link *search_result; - - search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr, - lnk->dst_port, port_net, - lnk->link_type, 0); - - if (search_result == NULL) - go_ahead = 1; - else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED) - && (search_result->flags & LINK_PARTIALLY_SPECIFIED)) - go_ahead = 1; - else - go_ahead = 0; - - if (go_ahead) { - if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS) - && (lnk->flags & LINK_PARTIALLY_SPECIFIED) - && ((lnk->link_type == LINK_TCP) || - (lnk->link_type == LINK_UDP))) { - if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) { - lnk->alias_port = port_net; - return (0); - } - } else { - lnk->alias_port = port_net; - return (0); - } - } - port_sys = random() & ALIAS_PORT_MASK; - port_sys += ALIAS_PORT_BASE; - port_net = htons(port_sys); - } - -#ifdef DEBUG - fprintf(stderr, "PacketAlias/GetnewPort(): "); - fprintf(stderr, "could not find free port\n"); -#endif - - return (-1); -} - - -static u_short -GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type) -{ - int err; - int sock; - struct sockaddr_in sock_addr; - - if (link_type == LINK_TCP) - sock = socket(AF_INET, SOCK_STREAM, 0); - else if (link_type == LINK_UDP) - sock = socket(AF_INET, SOCK_DGRAM, 0); - else { -#ifdef DEBUG - fprintf(stderr, "PacketAlias/GetSocket(): "); - fprintf(stderr, "incorrect link type\n"); -#endif - return (0); - } - - if (sock < 0) { -#ifdef DEBUG - fprintf(stderr, "PacketAlias/GetSocket(): "); - fprintf(stderr, "socket() error %d\n", *sockfd); -#endif - return (0); - } - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); - sock_addr.sin_port = port_net; - - err = bind(sock, - (struct sockaddr *)&sock_addr, - sizeof(sock_addr)); - if (err == 0) { - la->sockCount++; - *sockfd = sock; - return (1); - } else { - close(sock); - return (0); - } -} - - -/* FindNewPortGroup() returns a base port number for an available - range of contiguous port numbers. Note that if a port number - is already in use, that does not mean that it cannot be used by - another link concurrently. This is because FindNewPortGroup() - looks for unused triplets: (dest addr, dest port, alias port). */ - -int -FindNewPortGroup(struct 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) -{ - int i, j; - int max_trials; - u_short port_sys; - int link_type; - - /* - * Get link_type from protocol - */ - - switch (proto) { - case IPPROTO_UDP: - link_type = LINK_UDP; - break; - case IPPROTO_TCP: - link_type = LINK_TCP; - break; - default: - return (0); - break; - } - - /* - * The aliasing port is automatically selected by one of two - * methods below: - */ - max_trials = GET_NEW_PORT_MAX_ATTEMPTS; - - if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) { - /* - * When the ALIAS_SAME_PORTS option is chosen, the first - * try will be the actual source port. If this is already - * in use, the remainder of the trials will be random. - */ - port_sys = ntohs(src_port); - - } else { - - /* First trial and all subsequent are random. */ - if (align == FIND_EVEN_ALIAS_BASE) - port_sys = random() & ALIAS_PORT_MASK_EVEN; - else - port_sys = random() & ALIAS_PORT_MASK; - - port_sys += ALIAS_PORT_BASE; - } - -/* Port number search */ - for (i = 0; i < max_trials; i++) { - - struct alias_link *search_result; - - for (j = 0; j < port_count; j++) - if (0 != (search_result = FindLinkIn(la, dst_addr, alias_addr, - dst_port, htons(port_sys + j), - link_type, 0))) - break; - - /* Found a good range, return base */ - if (j == port_count) - return (htons(port_sys)); - - /* Find a new base to try */ - if (align == FIND_EVEN_ALIAS_BASE) - port_sys = random() & ALIAS_PORT_MASK_EVEN; - else - port_sys = random() & ALIAS_PORT_MASK; - - port_sys += ALIAS_PORT_BASE; - } - -#ifdef DEBUG - fprintf(stderr, "PacketAlias/FindNewPortGroup(): "); - fprintf(stderr, "could not find free port(s)\n"); -#endif - - return (0); -} - -static void -CleanupAliasData(struct libalias *la) -{ - struct alias_link *lnk; - int i, icount; - - icount = 0; - for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) { - lnk = LIST_FIRST(&la->linkTableOut[i]); - while (lnk != NULL) { - struct alias_link *link_next; - - link_next = LIST_NEXT(lnk, list_out); - icount++; - DeleteLink(lnk); - lnk = link_next; - } - } - - la->cleanupIndex = 0; -} - - -static void -IncrementalCleanup(struct libalias *la) -{ - int icount; - struct alias_link *lnk; - - icount = 0; - lnk = LIST_FIRST(&la->linkTableOut[la->cleanupIndex++]); - while (lnk != NULL) { - int idelta; - struct alias_link *link_next; - - link_next = LIST_NEXT(lnk, list_out); - idelta = la->timeStamp - lnk->timestamp; - switch (lnk->link_type) { - case LINK_TCP: - if (idelta > lnk->expire_time) { - struct tcp_dat *tcp_aux; - - tcp_aux = lnk->data.tcp; - if (tcp_aux->state.in != ALIAS_TCP_STATE_CONNECTED - || tcp_aux->state.out != ALIAS_TCP_STATE_CONNECTED) { - DeleteLink(lnk); - icount++; - } - } - break; - default: - if (idelta > lnk->expire_time) { - DeleteLink(lnk); - icount++; - } - break; - } - lnk = link_next; - } - - if (la->cleanupIndex == LINK_TABLE_OUT_SIZE) - la->cleanupIndex = 0; -} - -static void -DeleteLink(struct alias_link *lnk) -{ - struct libalias *la = lnk->la; - -/* Don't do anything if the link is marked permanent */ - if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT) - return; - -#ifndef NO_FW_PUNCH -/* Delete associated firewall hole, if any */ - ClearFWHole(lnk); -#endif - -/* Free memory allocated for LSNAT server pool */ - if (lnk->server != NULL) { - struct server *head, *curr, *next; - - head = curr = lnk->server; - do { - next = curr->next; - free(curr); - } while ((curr = next) != head); - } -/* Adjust output table pointers */ - LIST_REMOVE(lnk, list_out); - -/* Adjust input table pointers */ - LIST_REMOVE(lnk, list_in); - -/* Close socket, if one has been allocated */ - if (lnk->sockfd != -1) { - la->sockCount--; - close(lnk->sockfd); - } -/* Link-type dependent cleanup */ - switch (lnk->link_type) { - case LINK_ICMP: - la->icmpLinkCount--; - break; - case LINK_UDP: - la->udpLinkCount--; - break; - case LINK_TCP: - la->tcpLinkCount--; - free(lnk->data.tcp); - break; - case LINK_PPTP: - la->pptpLinkCount--; - break; - case LINK_FRAGMENT_ID: - la->fragmentIdLinkCount--; - break; - case LINK_FRAGMENT_PTR: - la->fragmentPtrLinkCount--; - if (lnk->data.frag_ptr != NULL) - free(lnk->data.frag_ptr); - break; - case LINK_ADDR: - break; - default: - la->protoLinkCount--; - break; - } - -/* Free memory */ - free(lnk); - -/* Write statistics, if logging enabled */ - if (la->packetAliasMode & PKT_ALIAS_LOG) { - ShowAliasStats(la); - } -} - - -static struct alias_link * -AddLink(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - struct in_addr alias_addr, - u_short src_port, - u_short dst_port, - int alias_port_param, /* if less than zero, alias */ - int link_type) -{ /* port will be automatically *//* chosen. - * If greater than */ - u_int start_point; /* zero, equal to alias port */ - struct alias_link *lnk; - - lnk = malloc(sizeof(struct alias_link)); - if (lnk != NULL) { - /* Basic initialization */ - lnk->la = la; - lnk->src_addr = src_addr; - lnk->dst_addr = dst_addr; - lnk->alias_addr = alias_addr; - lnk->proxy_addr.s_addr = INADDR_ANY; - lnk->src_port = src_port; - lnk->dst_port = dst_port; - lnk->proxy_port = 0; - lnk->server = NULL; - lnk->link_type = link_type; - lnk->sockfd = -1; - lnk->flags = 0; - lnk->pflags = 0; - lnk->timestamp = la->timeStamp; - - /* Expiration time */ - switch (link_type) { - case LINK_ICMP: - lnk->expire_time = ICMP_EXPIRE_TIME; - break; - case LINK_UDP: - lnk->expire_time = UDP_EXPIRE_TIME; - break; - case LINK_TCP: - lnk->expire_time = TCP_EXPIRE_INITIAL; - break; - case LINK_PPTP: - lnk->flags |= LINK_PERMANENT; /* no timeout. */ - break; - case LINK_FRAGMENT_ID: - lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME; - break; - case LINK_FRAGMENT_PTR: - lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME; - break; - case LINK_ADDR: - break; - default: - lnk->expire_time = PROTO_EXPIRE_TIME; - break; - } - - /* Determine alias flags */ - if (dst_addr.s_addr == INADDR_ANY) - lnk->flags |= LINK_UNKNOWN_DEST_ADDR; - if (dst_port == 0) - lnk->flags |= LINK_UNKNOWN_DEST_PORT; - - /* Determine alias port */ - if (GetNewPort(la, lnk, alias_port_param) != 0) { - free(lnk); - return (NULL); - } - /* Link-type dependent initialization */ - switch (link_type) { - struct tcp_dat *aux_tcp; - - case LINK_ICMP: - la->icmpLinkCount++; - break; - case LINK_UDP: - la->udpLinkCount++; - break; - case LINK_TCP: - aux_tcp = malloc(sizeof(struct tcp_dat)); - if (aux_tcp != NULL) { - int i; - - la->tcpLinkCount++; - aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED; - aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED; - aux_tcp->state.index = 0; - aux_tcp->state.ack_modified = 0; - for (i = 0; i < N_LINK_TCP_DATA; i++) - aux_tcp->ack[i].active = 0; - aux_tcp->fwhole = -1; - lnk->data.tcp = aux_tcp; - } else { -#ifdef DEBUG - fprintf(stderr, "PacketAlias/AddLink: "); - fprintf(stderr, " cannot allocate auxiliary TCP data\n"); -#endif - free(lnk); - return (NULL); - } - break; - case LINK_PPTP: - la->pptpLinkCount++; - break; - case LINK_FRAGMENT_ID: - la->fragmentIdLinkCount++; - break; - case LINK_FRAGMENT_PTR: - la->fragmentPtrLinkCount++; - break; - case LINK_ADDR: - break; - default: - la->protoLinkCount++; - break; - } - - /* Set up pointers for output lookup table */ - start_point = StartPointOut(src_addr, dst_addr, - src_port, dst_port, link_type); - LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out); - - /* Set up pointers for input lookup table */ - start_point = StartPointIn(alias_addr, lnk->alias_port, link_type); - LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in); - } else { -#ifdef DEBUG - fprintf(stderr, "PacketAlias/AddLink(): "); - fprintf(stderr, "malloc() call failed.\n"); -#endif - } - - if (la->packetAliasMode & PKT_ALIAS_LOG) { - ShowAliasStats(la); - } - return (lnk); -} - -static struct alias_link * -ReLink(struct alias_link *old_lnk, - struct in_addr src_addr, - struct in_addr dst_addr, - struct in_addr alias_addr, - u_short src_port, - u_short dst_port, - int alias_port_param, /* if less than zero, alias */ - int link_type) -{ /* port will be automatically *//* chosen. - * If greater than */ - struct alias_link *new_lnk; /* zero, equal to alias port */ - struct libalias *la = old_lnk->la; - - new_lnk = AddLink(la, src_addr, dst_addr, alias_addr, - src_port, dst_port, alias_port_param, - link_type); -#ifndef NO_FW_PUNCH - if (new_lnk != NULL && - old_lnk->link_type == LINK_TCP && - old_lnk->data.tcp->fwhole > 0) { - PunchFWHole(new_lnk); - } -#endif - DeleteLink(old_lnk); - return (new_lnk); -} - -static struct alias_link * -_FindLinkOut(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - u_short src_port, - u_short dst_port, - int link_type, - int replace_partial_links) -{ - u_int i; - struct alias_link *lnk; - - i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type); - LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) { - if (lnk->src_addr.s_addr == src_addr.s_addr - && lnk->server == NULL - && lnk->dst_addr.s_addr == dst_addr.s_addr - && lnk->dst_port == dst_port - && lnk->src_port == src_port - && lnk->link_type == link_type) { - lnk->timestamp = la->timeStamp; - break; - } - } - -/* Search for partially specified links. */ - if (lnk == NULL && replace_partial_links) { - if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) { - lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0, - link_type, 0); - if (lnk == NULL) - lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, - dst_port, link_type, 0); - } - if (lnk == NULL && - (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) { - lnk = _FindLinkOut(la, src_addr, la->nullAddress, src_port, 0, - link_type, 0); - } - if (lnk != NULL) { - lnk = ReLink(lnk, - src_addr, dst_addr, lnk->alias_addr, - src_port, dst_port, lnk->alias_port, - link_type); - } - } - return (lnk); -} - -static struct alias_link * -FindLinkOut(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - u_short src_port, - u_short dst_port, - int link_type, - int replace_partial_links) -{ - struct alias_link *lnk; - - lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, - link_type, replace_partial_links); - - if (lnk == NULL) { - /* - * The following allows permanent links to be specified as - * using the default source address (i.e. device interface - * address) without knowing in advance what that address - * is. - */ - if (la->aliasAddress.s_addr != INADDR_ANY && - src_addr.s_addr == la->aliasAddress.s_addr) { - lnk = _FindLinkOut(la, la->nullAddress, dst_addr, src_port, dst_port, - link_type, replace_partial_links); - } - } - return (lnk); -} - - -static struct alias_link * -_FindLinkIn(struct libalias *la, struct in_addr dst_addr, - struct in_addr alias_addr, - u_short dst_port, - u_short alias_port, - int link_type, - int replace_partial_links) -{ - int flags_in; - u_int start_point; - struct alias_link *lnk; - struct alias_link *lnk_fully_specified; - struct alias_link *lnk_unknown_all; - struct alias_link *lnk_unknown_dst_addr; - struct alias_link *lnk_unknown_dst_port; - -/* Initialize pointers */ - lnk_fully_specified = NULL; - lnk_unknown_all = NULL; - lnk_unknown_dst_addr = NULL; - lnk_unknown_dst_port = NULL; - -/* If either the dest addr or port is unknown, the search - loop will have to know about this. */ - - flags_in = 0; - if (dst_addr.s_addr == INADDR_ANY) - flags_in |= LINK_UNKNOWN_DEST_ADDR; - if (dst_port == 0) - flags_in |= LINK_UNKNOWN_DEST_PORT; - -/* Search loop */ - start_point = StartPointIn(alias_addr, alias_port, link_type); - LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) { - int flags; - - flags = flags_in | lnk->flags; - if (!(flags & LINK_PARTIALLY_SPECIFIED)) { - if (lnk->alias_addr.s_addr == alias_addr.s_addr - && lnk->alias_port == alias_port - && lnk->dst_addr.s_addr == dst_addr.s_addr - && lnk->dst_port == dst_port - && lnk->link_type == link_type) { - lnk_fully_specified = lnk; - break; - } - } else if ((flags & LINK_UNKNOWN_DEST_ADDR) - && (flags & LINK_UNKNOWN_DEST_PORT)) { - if (lnk->alias_addr.s_addr == alias_addr.s_addr - && lnk->alias_port == alias_port - && lnk->link_type == link_type) { - if (lnk_unknown_all == NULL) - lnk_unknown_all = lnk; - } - } else if (flags & LINK_UNKNOWN_DEST_ADDR) { - if (lnk->alias_addr.s_addr == alias_addr.s_addr - && lnk->alias_port == alias_port - && lnk->link_type == link_type - && lnk->dst_port == dst_port) { - if (lnk_unknown_dst_addr == NULL) - lnk_unknown_dst_addr = lnk; - } - } else if (flags & LINK_UNKNOWN_DEST_PORT) { - if (lnk->alias_addr.s_addr == alias_addr.s_addr - && lnk->alias_port == alias_port - && lnk->link_type == link_type - && lnk->dst_addr.s_addr == dst_addr.s_addr) { - if (lnk_unknown_dst_port == NULL) - lnk_unknown_dst_port = lnk; - } - } - } - - - - if (lnk_fully_specified != NULL) { - lnk_fully_specified->timestamp = la->timeStamp; - lnk = lnk_fully_specified; - } else if (lnk_unknown_dst_port != NULL) - lnk = lnk_unknown_dst_port; - else if (lnk_unknown_dst_addr != NULL) - lnk = lnk_unknown_dst_addr; - else if (lnk_unknown_all != NULL) - lnk = lnk_unknown_all; - else - return (NULL); - - if (replace_partial_links && - (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) { - struct in_addr src_addr; - u_short src_port; - - if (lnk->server != NULL) { /* LSNAT link */ - src_addr = lnk->server->addr; - src_port = lnk->server->port; - lnk->server = lnk->server->next; - } else { - src_addr = lnk->src_addr; - src_port = lnk->src_port; - } - - lnk = ReLink(lnk, - src_addr, dst_addr, alias_addr, - src_port, dst_port, alias_port, - link_type); - } - return (lnk); -} - -static struct alias_link * -FindLinkIn(struct libalias *la, struct in_addr dst_addr, - struct in_addr alias_addr, - u_short dst_port, - u_short alias_port, - int link_type, - int replace_partial_links) -{ - struct alias_link *lnk; - - lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port, - link_type, replace_partial_links); - - if (lnk == NULL) { - /* - * The following allows permanent links to be specified as - * using the default aliasing address (i.e. device - * interface address) without knowing in advance what that - * address is. - */ - if (la->aliasAddress.s_addr != INADDR_ANY && - alias_addr.s_addr == la->aliasAddress.s_addr) { - lnk = _FindLinkIn(la, dst_addr, la->nullAddress, dst_port, alias_port, - link_type, replace_partial_links); - } - } - return (lnk); -} - - - - -/* External routines for finding/adding links - --- "external" means outside alias_db.c, but within alias*.c -- - - FindIcmpIn(), FindIcmpOut() - FindFragmentIn1(), FindFragmentIn2() - AddFragmentPtrLink(), FindFragmentPtr() - FindProtoIn(), FindProtoOut() - FindUdpTcpIn(), FindUdpTcpOut() - AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(), - FindPptpOutByPeerCallId(), FindPptpInByPeerCallId() - FindOriginalAddress(), FindAliasAddress() - -(prototypes in alias_local.h) -*/ - - -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 *lnk; - - lnk = FindLinkIn(la, dst_addr, alias_addr, - NO_DEST_PORT, id_alias, - LINK_ICMP, 0); - if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { - struct in_addr target_addr; - - target_addr = FindOriginalAddress(la, alias_addr); - lnk = AddLink(la, target_addr, dst_addr, alias_addr, - id_alias, NO_DEST_PORT, id_alias, - LINK_ICMP); - } - return (lnk); -} - - -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 *lnk; - - lnk = FindLinkOut(la, src_addr, dst_addr, - id, NO_DEST_PORT, - LINK_ICMP, 0); - if (lnk == NULL && create) { - struct in_addr alias_addr; - - alias_addr = FindAliasAddress(la, src_addr); - lnk = AddLink(la, src_addr, dst_addr, alias_addr, - id, NO_DEST_PORT, GET_ALIAS_ID, - LINK_ICMP); - } - return (lnk); -} - - -struct alias_link * -FindFragmentIn1(struct libalias *la, struct in_addr dst_addr, - struct in_addr alias_addr, - u_short ip_id) -{ - struct alias_link *lnk; - - lnk = FindLinkIn(la, dst_addr, alias_addr, - NO_DEST_PORT, ip_id, - LINK_FRAGMENT_ID, 0); - - if (lnk == NULL) { - lnk = AddLink(la, la->nullAddress, dst_addr, alias_addr, - NO_SRC_PORT, NO_DEST_PORT, ip_id, - LINK_FRAGMENT_ID); - } - return (lnk); -} - - -struct alias_link * -FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a link if - * one */ - struct in_addr alias_addr, /* is not found. */ - u_short ip_id) -{ - return FindLinkIn(la, dst_addr, alias_addr, - NO_DEST_PORT, ip_id, - LINK_FRAGMENT_ID, 0); -} - - -struct alias_link * -AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr, - u_short ip_id) -{ - return AddLink(la, la->nullAddress, dst_addr, la->nullAddress, - NO_SRC_PORT, NO_DEST_PORT, ip_id, - LINK_FRAGMENT_PTR); -} - - -struct alias_link * -FindFragmentPtr(struct libalias *la, struct in_addr dst_addr, - u_short ip_id) -{ - return FindLinkIn(la, dst_addr, la->nullAddress, - NO_DEST_PORT, ip_id, - LINK_FRAGMENT_PTR, 0); -} - - -struct alias_link * -FindProtoIn(struct libalias *la, struct in_addr dst_addr, - struct in_addr alias_addr, - u_char proto) -{ - struct alias_link *lnk; - - lnk = FindLinkIn(la, dst_addr, alias_addr, - NO_DEST_PORT, 0, - proto, 1); - - if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { - struct in_addr target_addr; - - target_addr = FindOriginalAddress(la, alias_addr); - lnk = AddLink(la, target_addr, dst_addr, alias_addr, - NO_SRC_PORT, NO_DEST_PORT, 0, - proto); - } - return (lnk); -} - - -struct alias_link * -FindProtoOut(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - u_char proto) -{ - struct alias_link *lnk; - - lnk = FindLinkOut(la, src_addr, dst_addr, - NO_SRC_PORT, NO_DEST_PORT, - proto, 1); - - if (lnk == NULL) { - struct in_addr alias_addr; - - alias_addr = FindAliasAddress(la, src_addr); - lnk = AddLink(la, src_addr, dst_addr, alias_addr, - NO_SRC_PORT, NO_DEST_PORT, 0, - proto); - } - return (lnk); -} - - -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) -{ - int link_type; - struct alias_link *lnk; - - switch (proto) { - case IPPROTO_UDP: - link_type = LINK_UDP; - break; - case IPPROTO_TCP: - link_type = LINK_TCP; - break; - default: - return (NULL); - break; - } - - lnk = FindLinkIn(la, dst_addr, alias_addr, - dst_port, alias_port, - link_type, create); - - if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) { - struct in_addr target_addr; - - target_addr = FindOriginalAddress(la, alias_addr); - lnk = AddLink(la, target_addr, dst_addr, alias_addr, - alias_port, dst_port, alias_port, - link_type); - } - return (lnk); -} - - -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) -{ - int link_type; - struct alias_link *lnk; - - switch (proto) { - case IPPROTO_UDP: - link_type = LINK_UDP; - break; - case IPPROTO_TCP: - link_type = LINK_TCP; - break; - default: - return (NULL); - break; - } - - lnk = FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, create); - - if (lnk == NULL && create) { - struct in_addr alias_addr; - - alias_addr = FindAliasAddress(la, src_addr); - lnk = AddLink(la, src_addr, dst_addr, alias_addr, - src_port, dst_port, GET_ALIAS_PORT, - link_type); - } - return (lnk); -} - - -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 *lnk; - - lnk = AddLink(la, src_addr, dst_addr, alias_addr, - src_call_id, 0, GET_ALIAS_PORT, - LINK_PPTP); - - return (lnk); -} - - -struct alias_link * -FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - u_int16_t src_call_id) -{ - u_int i; - struct alias_link *lnk; - - i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); - LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) - if (lnk->link_type == LINK_PPTP && - lnk->src_addr.s_addr == src_addr.s_addr && - lnk->dst_addr.s_addr == dst_addr.s_addr && - lnk->src_port == src_call_id) - break; - - return (lnk); -} - - -struct alias_link * -FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - u_int16_t dst_call_id) -{ - u_int i; - struct alias_link *lnk; - - i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); - LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) - if (lnk->link_type == LINK_PPTP && - lnk->src_addr.s_addr == src_addr.s_addr && - lnk->dst_addr.s_addr == dst_addr.s_addr && - lnk->dst_port == dst_call_id) - break; - - return (lnk); -} - - -struct alias_link * -FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr, - struct in_addr alias_addr, - u_int16_t dst_call_id) -{ - u_int i; - struct alias_link *lnk; - - i = StartPointIn(alias_addr, 0, LINK_PPTP); - LIST_FOREACH(lnk, &la->linkTableIn[i], list_in) - if (lnk->link_type == LINK_PPTP && - lnk->dst_addr.s_addr == dst_addr.s_addr && - lnk->alias_addr.s_addr == alias_addr.s_addr && - lnk->dst_port == dst_call_id) - break; - - return (lnk); -} - - -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 *lnk; - - lnk = FindLinkIn(la, dst_addr, alias_addr, - 0 /* any */ , alias_call_id, - LINK_PPTP, 0); - - - return (lnk); -} - - -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) -{ - int link_type; - struct alias_link *lnk; - - switch (proto) { - case IPPROTO_UDP: - link_type = LINK_UDP; - break; - case IPPROTO_TCP: - link_type = LINK_TCP; - break; - default: - return (NULL); - break; - } - - lnk = FindLinkOut(la, src_addr, dst_addr, src_port, 0, link_type, 1); - - if (lnk == NULL) { - struct in_addr alias_addr; - - alias_addr = FindAliasAddress(la, src_addr); - lnk = AddLink(la, src_addr, dst_addr, alias_addr, - src_port, 0, alias_port, - link_type); - } - return (lnk); -} - - -struct in_addr -FindOriginalAddress(struct libalias *la, struct in_addr alias_addr) -{ - struct alias_link *lnk; - - lnk = FindLinkIn(la, la->nullAddress, alias_addr, - 0, 0, LINK_ADDR, 0); - if (lnk == NULL) { - la->newDefaultLink = 1; - if (la->targetAddress.s_addr == INADDR_ANY) - return (alias_addr); - else if (la->targetAddress.s_addr == INADDR_NONE) - return (la->aliasAddress.s_addr != INADDR_ANY) ? - la->aliasAddress : alias_addr; - else - return (la->targetAddress); - } else { - if (lnk->server != NULL) { /* LSNAT link */ - struct in_addr src_addr; - - src_addr = lnk->server->addr; - lnk->server = lnk->server->next; - return (src_addr); - } else if (lnk->src_addr.s_addr == INADDR_ANY) - return (la->aliasAddress.s_addr != INADDR_ANY) ? - la->aliasAddress : alias_addr; - else - return (lnk->src_addr); - } -} - - -struct in_addr -FindAliasAddress(struct libalias *la, struct in_addr original_addr) -{ - struct alias_link *lnk; - - lnk = FindLinkOut(la, original_addr, la->nullAddress, - 0, 0, LINK_ADDR, 0); - if (lnk == NULL) { - return (la->aliasAddress.s_addr != INADDR_ANY) ? - la->aliasAddress : original_addr; - } else { - if (lnk->alias_addr.s_addr == INADDR_ANY) - return (la->aliasAddress.s_addr != INADDR_ANY) ? - la->aliasAddress : original_addr; - else - return (lnk->alias_addr); - } -} - - -/* External routines for getting or changing link data - (external to alias_db.c, but internal to alias*.c) - - SetFragmentData(), GetFragmentData() - SetFragmentPtr(), GetFragmentPtr() - SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut() - GetOriginalAddress(), GetDestAddress(), GetAliasAddress() - GetOriginalPort(), GetAliasPort() - SetAckModified(), GetAckModified() - GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq() - SetProtocolFlags(), GetProtocolFlags() - SetDestCallId() -*/ - - -void -SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr) -{ - lnk->data.frag_addr = src_addr; -} - - -void -GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr) -{ - *src_addr = lnk->data.frag_addr; -} - - -void -SetFragmentPtr(struct alias_link *lnk, char *fptr) -{ - lnk->data.frag_ptr = fptr; -} - - -void -GetFragmentPtr(struct alias_link *lnk, char **fptr) -{ - *fptr = lnk->data.frag_ptr; -} - - -void -SetStateIn(struct alias_link *lnk, int state) -{ - /* TCP input state */ - switch (state) { - case ALIAS_TCP_STATE_DISCONNECTED: - if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED) - lnk->expire_time = TCP_EXPIRE_DEAD; - else - lnk->expire_time = TCP_EXPIRE_SINGLEDEAD; - break; - case ALIAS_TCP_STATE_CONNECTED: - if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED) - lnk->expire_time = TCP_EXPIRE_CONNECTED; - break; - default: - abort(); - } - lnk->data.tcp->state.in = state; -} - - -void -SetStateOut(struct alias_link *lnk, int state) -{ - /* TCP output state */ - switch (state) { - case ALIAS_TCP_STATE_DISCONNECTED: - if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED) - lnk->expire_time = TCP_EXPIRE_DEAD; - else - lnk->expire_time = TCP_EXPIRE_SINGLEDEAD; - break; - case ALIAS_TCP_STATE_CONNECTED: - if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED) - lnk->expire_time = TCP_EXPIRE_CONNECTED; - break; - default: - abort(); - } - lnk->data.tcp->state.out = state; -} - - -int -GetStateIn(struct alias_link *lnk) -{ - /* TCP input state */ - return (lnk->data.tcp->state.in); -} - - -int -GetStateOut(struct alias_link *lnk) -{ - /* TCP output state */ - return (lnk->data.tcp->state.out); -} - - -struct in_addr -GetOriginalAddress(struct alias_link *lnk) -{ - if (lnk->src_addr.s_addr == INADDR_ANY) - return (lnk->la->aliasAddress); - else - return (lnk->src_addr); -} - - -struct in_addr -GetDestAddress(struct alias_link *lnk) -{ - return (lnk->dst_addr); -} - - -struct in_addr -GetAliasAddress(struct alias_link *lnk) -{ - if (lnk->alias_addr.s_addr == INADDR_ANY) - return (lnk->la->aliasAddress); - else - return (lnk->alias_addr); -} - - -struct in_addr -GetDefaultAliasAddress(struct libalias *la) -{ - return (la->aliasAddress); -} - - -void -SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr) -{ - la->aliasAddress = alias_addr; -} - - -u_short -GetOriginalPort(struct alias_link *lnk) -{ - return (lnk->src_port); -} - - -u_short -GetAliasPort(struct alias_link *lnk) -{ - return (lnk->alias_port); -} - -#ifndef NO_FW_PUNCH -static u_short -GetDestPort(struct alias_link *lnk) -{ - return (lnk->dst_port); -} - -#endif - -void -SetAckModified(struct alias_link *lnk) -{ -/* Indicate that ACK numbers have been modified in a TCP connection */ - lnk->data.tcp->state.ack_modified = 1; -} - - -struct in_addr -GetProxyAddress(struct alias_link *lnk) -{ - return (lnk->proxy_addr); -} - - -void -SetProxyAddress(struct alias_link *lnk, struct in_addr addr) -{ - lnk->proxy_addr = addr; -} - - -u_short -GetProxyPort(struct alias_link *lnk) -{ - return (lnk->proxy_port); -} - - -void -SetProxyPort(struct alias_link *lnk, u_short port) -{ - lnk->proxy_port = port; -} - - -int -GetAckModified(struct alias_link *lnk) -{ -/* See if ACK numbers have been modified */ - return (lnk->data.tcp->state.ack_modified); -} - - -int -GetDeltaAckIn(struct ip *pip, struct alias_link *lnk) -{ -/* -Find out how much the ACK number has been altered for an incoming -TCP packet. To do this, a circular list of ACK numbers where the TCP -packet size was altered is searched. -*/ - - int i; - struct tcphdr *tc; - int delta, ack_diff_min; - u_long ack; - - tc = ip_next(pip); - ack = tc->th_ack; - - delta = 0; - ack_diff_min = -1; - for (i = 0; i < N_LINK_TCP_DATA; i++) { - struct ack_data_record x; - - x = lnk->data.tcp->ack[i]; - if (x.active == 1) { - int ack_diff; - - ack_diff = SeqDiff(x.ack_new, ack); - if (ack_diff >= 0) { - if (ack_diff_min >= 0) { - if (ack_diff < ack_diff_min) { - delta = x.delta; - ack_diff_min = ack_diff; - } - } else { - delta = x.delta; - ack_diff_min = ack_diff; - } - } - } - } - return (delta); -} - - -int -GetDeltaSeqOut(struct ip *pip, struct alias_link *lnk) -{ -/* -Find out how much the sequence number has been altered for an outgoing -TCP packet. To do this, a circular list of ACK numbers where the TCP -packet size was altered is searched. -*/ - - int i; - struct tcphdr *tc; - int delta, seq_diff_min; - u_long seq; - - tc = ip_next(pip); - seq = tc->th_seq; - - delta = 0; - seq_diff_min = -1; - for (i = 0; i < N_LINK_TCP_DATA; i++) { - struct ack_data_record x; - - x = lnk->data.tcp->ack[i]; - if (x.active == 1) { - int seq_diff; - - seq_diff = SeqDiff(x.ack_old, seq); - if (seq_diff >= 0) { - if (seq_diff_min >= 0) { - if (seq_diff < seq_diff_min) { - delta = x.delta; - seq_diff_min = seq_diff; - } - } else { - delta = x.delta; - seq_diff_min = seq_diff; - } - } - } - } - return (delta); -} - - -void -AddSeq(struct ip *pip, struct alias_link *lnk, int delta) -{ -/* -When a TCP packet has been altered in length, save this -information in a circular list. If enough packets have -been altered, then this list will begin to overwrite itself. -*/ - - struct tcphdr *tc; - struct ack_data_record x; - int hlen, tlen, dlen; - int i; - - tc = ip_next(pip); - - hlen = (pip->ip_hl + tc->th_off) << 2; - tlen = ntohs(pip->ip_len); - dlen = tlen - hlen; - - x.ack_old = htonl(ntohl(tc->th_seq) + dlen); - x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta); - x.delta = delta; - x.active = 1; - - i = lnk->data.tcp->state.index; - lnk->data.tcp->ack[i] = x; - - i++; - if (i == N_LINK_TCP_DATA) - lnk->data.tcp->state.index = 0; - else - lnk->data.tcp->state.index = i; -} - -void -SetExpire(struct alias_link *lnk, int expire) -{ - if (expire == 0) { - lnk->flags &= ~LINK_PERMANENT; - DeleteLink(lnk); - } else if (expire == -1) { - lnk->flags |= LINK_PERMANENT; - } else if (expire > 0) { - lnk->expire_time = expire; - } else { -#ifdef DEBUG - fprintf(stderr, "PacketAlias/SetExpire(): "); - fprintf(stderr, "error in expire parameter\n"); -#endif - } -} - -void -ClearCheckNewLink(struct libalias *la) -{ - la->newDefaultLink = 0; -} - -void -SetProtocolFlags(struct alias_link *lnk, int pflags) -{ - - lnk->pflags = pflags;; -} - -int -GetProtocolFlags(struct alias_link *lnk) -{ - - return (lnk->pflags); -} - -void -SetDestCallId(struct alias_link *lnk, u_int16_t cid) -{ - struct libalias *la = lnk->la; - - la->deleteAllLinks = 1; - lnk = ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr, - lnk->src_port, cid, lnk->alias_port, lnk->link_type); - la->deleteAllLinks = 0; -} - - -/* Miscellaneous Functions - - HouseKeeping() - InitPacketAliasLog() - UninitPacketAliasLog() -*/ - -/* - Whenever an outgoing or incoming packet is handled, HouseKeeping() - is called to find and remove timed-out aliasing links. Logic exists - to sweep through the entire table and linked list structure - every 60 seconds. - - (prototype in alias_local.h) -*/ - -void -HouseKeeping(struct libalias *la) -{ - int i, n, n100; - struct timeval tv; - struct timezone tz; - - /* - * Save system time (seconds) in global variable timeStamp for use - * by other functions. This is done so as not to unnecessarily - * waste timeline by making system calls. - */ - gettimeofday(&tv, &tz); - la->timeStamp = tv.tv_sec; - - /* Compute number of spokes (output table link chains) to cover */ - n100 = LINK_TABLE_OUT_SIZE * 100 + la->houseKeepingResidual; - n100 *= la->timeStamp - la->lastCleanupTime; - n100 /= ALIAS_CLEANUP_INTERVAL_SECS; - - n = n100 / 100; - - /* Handle different cases */ - if (n > ALIAS_CLEANUP_MAX_SPOKES) { - n = ALIAS_CLEANUP_MAX_SPOKES; - la->lastCleanupTime = la->timeStamp; - la->houseKeepingResidual = 0; - - for (i = 0; i < n; i++) - IncrementalCleanup(la); - } else if (n > 0) { - la->lastCleanupTime = la->timeStamp; - la->houseKeepingResidual = n100 - 100 * n; - - for (i = 0; i < n; i++) - IncrementalCleanup(la); - } else if (n < 0) { -#ifdef DEBUG - fprintf(stderr, "PacketAlias/HouseKeeping(): "); - fprintf(stderr, "something unexpected in time values\n"); -#endif - la->lastCleanupTime = la->timeStamp; - la->houseKeepingResidual = 0; - } -} - - -/* Init the log file and enable logging */ -static void -InitPacketAliasLog(struct libalias *la) -{ - if ((~la->packetAliasMode & PKT_ALIAS_LOG) - && (la->monitorFile = fopen("/var/log/alias.log", "w"))) { - la->packetAliasMode |= PKT_ALIAS_LOG; - fprintf(la->monitorFile, - "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n"); - } -} - - -/* Close the log-file and disable logging. */ -static void -UninitPacketAliasLog(struct libalias *la) -{ - if (la->monitorFile) { - fclose(la->monitorFile); - la->monitorFile = NULL; - } - la->packetAliasMode &= ~PKT_ALIAS_LOG; -} - - - - - - -/* Outside world interfaces - --- "outside world" means other than alias*.c routines -- - - PacketAliasRedirectPort() - PacketAliasAddServer() - PacketAliasRedirectProto() - PacketAliasRedirectAddr() - PacketAliasRedirectDynamic() - PacketAliasRedirectDelete() - PacketAliasSetAddress() - PacketAliasInit() - PacketAliasUninit() - PacketAliasSetMode() - -(prototypes in alias.h) -*/ - -/* Redirection from a specific public addr:port to a - private addr:port */ -struct alias_link * -LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port, - struct in_addr dst_addr, u_short dst_port, - struct in_addr alias_addr, u_short alias_port, - u_char proto) -{ - int link_type; - struct alias_link *lnk; - - switch (proto) { - case IPPROTO_UDP: - link_type = LINK_UDP; - break; - case IPPROTO_TCP: - link_type = LINK_TCP; - break; - default: -#ifdef DEBUG - fprintf(stderr, "PacketAliasRedirectPort(): "); - fprintf(stderr, "only TCP and UDP protocols allowed\n"); -#endif - return (NULL); - } - - lnk = AddLink(la, src_addr, dst_addr, alias_addr, - src_port, dst_port, alias_port, - link_type); - - if (lnk != NULL) { - lnk->flags |= LINK_PERMANENT; - } -#ifdef DEBUG - else { - fprintf(stderr, "PacketAliasRedirectPort(): " - "call to AddLink() failed\n"); - } -#endif - - return (lnk); -} - -/* Add server to the pool of servers */ -int -LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port) -{ - struct server *server; - - (void)la; - - server = malloc(sizeof(struct server)); - - if (server != NULL) { - struct server *head; - - server->addr = addr; - server->port = port; - - head = lnk->server; - if (head == NULL) - server->next = server; - else { - struct server *s; - - for (s = head; s->next != head; s = s->next); - s->next = server; - server->next = head; - } - lnk->server = server; - return (0); - } else - return (-1); -} - -/* Redirect packets of a given IP protocol from a specific - public address to a private address */ -struct alias_link * -LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - struct in_addr alias_addr, - u_char proto) -{ - struct alias_link *lnk; - - lnk = AddLink(la, src_addr, dst_addr, alias_addr, - NO_SRC_PORT, NO_DEST_PORT, 0, - proto); - - if (lnk != NULL) { - lnk->flags |= LINK_PERMANENT; - } -#ifdef DEBUG - else { - fprintf(stderr, "PacketAliasRedirectProto(): " - "call to AddLink() failed\n"); - } -#endif - - return (lnk); -} - -/* Static address translation */ -struct alias_link * -LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr, - struct in_addr alias_addr) -{ - struct alias_link *lnk; - - lnk = AddLink(la, src_addr, la->nullAddress, alias_addr, - 0, 0, 0, - LINK_ADDR); - - if (lnk != NULL) { - lnk->flags |= LINK_PERMANENT; - } -#ifdef DEBUG - else { - fprintf(stderr, "PacketAliasRedirectAddr(): " - "call to AddLink() failed\n"); - } -#endif - - return (lnk); -} - - -/* Mark the aliasing link dynamic */ -int -LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk) -{ - - (void)la; - - if (lnk->flags & LINK_PARTIALLY_SPECIFIED) - return (-1); - else { - lnk->flags &= ~LINK_PERMANENT; - return (0); - } -} - - -void -LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk) -{ -/* This is a dangerous function to put in the API, - because an invalid pointer can crash the program. */ - - la->deleteAllLinks = 1; - DeleteLink(lnk); - la->deleteAllLinks = 0; -} - - -void -LibAliasSetAddress(struct libalias *la, struct in_addr addr) -{ - if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE - && la->aliasAddress.s_addr != addr.s_addr) - CleanupAliasData(la); - - la->aliasAddress = addr; -} - - -void -LibAliasSetTarget(struct libalias *la, struct in_addr target_addr) -{ - la->targetAddress = target_addr; -} - -static void -finishoff(void) -{ - - while (!LIST_EMPTY(&instancehead)) - LibAliasUninit(LIST_FIRST(&instancehead)); -} - -struct libalias * -LibAliasInit(struct libalias *la) -{ - int i; - struct timeval tv; - struct timezone tz; - - if (la == NULL) { - la = calloc(sizeof *la, 1); - if (la == NULL) - return (la); - if (LIST_EMPTY(&instancehead)) - atexit(finishoff); - LIST_INSERT_HEAD(&instancehead, la, instancelist); - - gettimeofday(&tv, &tz); - la->timeStamp = tv.tv_sec; - la->lastCleanupTime = tv.tv_sec; - la->houseKeepingResidual = 0; - - for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) - LIST_INIT(&la->linkTableOut[i]); - for (i = 0; i < LINK_TABLE_IN_SIZE; i++) - LIST_INIT(&la->linkTableIn[i]); - - } else { - la->deleteAllLinks = 1; - CleanupAliasData(la); - la->deleteAllLinks = 0; - } - - la->aliasAddress.s_addr = INADDR_ANY; - la->targetAddress.s_addr = INADDR_ANY; - - la->icmpLinkCount = 0; - la->udpLinkCount = 0; - la->tcpLinkCount = 0; - la->pptpLinkCount = 0; - la->protoLinkCount = 0; - la->fragmentIdLinkCount = 0; - la->fragmentPtrLinkCount = 0; - la->sockCount = 0; - - la->cleanupIndex = 0; - - la->packetAliasMode = PKT_ALIAS_SAME_PORTS - | PKT_ALIAS_USE_SOCKETS - | PKT_ALIAS_RESET_ON_ADDR_CHANGE; -#ifndef NO_FW_PUNCH - la->fireWallFD = -1; -#endif - return (la); -} - -void -LibAliasUninit(struct libalias *la) -{ - la->deleteAllLinks = 1; - CleanupAliasData(la); - la->deleteAllLinks = 0; - UninitPacketAliasLog(la); -#ifndef NO_FW_PUNCH - UninitPunchFW(la); -#endif - LIST_REMOVE(la, instancelist); - free(la); -} - -/* Change mode for some operations */ -unsigned int -LibAliasSetMode( - struct libalias *la, - unsigned int flags, /* Which state to bring flags to */ - unsigned int mask /* Mask of which flags to affect (use 0 to - * do a probe for flag values) */ -) -{ -/* Enable logging? */ - if (flags & mask & PKT_ALIAS_LOG) { - InitPacketAliasLog(la); /* Do the enable */ - } else -/* _Disable_ logging? */ - if (~flags & mask & PKT_ALIAS_LOG) { - UninitPacketAliasLog(la); - } -#ifndef NO_FW_PUNCH -/* Start punching holes in the firewall? */ - if (flags & mask & PKT_ALIAS_PUNCH_FW) { - InitPunchFW(la); - } else -/* Stop punching holes in the firewall? */ - if (~flags & mask & PKT_ALIAS_PUNCH_FW) { - UninitPunchFW(la); - } -#endif - -/* Other flags can be set/cleared without special action */ - la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask); - return (la->packetAliasMode); -} - - -int -LibAliasCheckNewLink(struct libalias *la) -{ - return (la->newDefaultLink); -} - - -#ifndef NO_FW_PUNCH - -/***************** - Code to support firewall punching. This shouldn't really be in this - file, but making variables global is evil too. - ****************/ - -#ifndef IPFW2 -#define IPFW2 1 /* use new ipfw code */ -#endif - -/* Firewall include files */ -#include -#include -#include -#include - -#if IPFW2 /* support for new firewall code */ -/* - * helper function, updates the pointer to cmd with the length - * of the current command, and also cleans up the first word of - * the new command in case it has been clobbered before. - */ -static ipfw_insn * -next_cmd(ipfw_insn * cmd) -{ - cmd += F_LEN(cmd); - bzero(cmd, sizeof(*cmd)); - return (cmd); -} - -/* - * A function to fill simple commands of size 1. - * Existing flags are preserved. - */ -static ipfw_insn * -fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size, - int flags, u_int16_t arg) -{ - cmd->opcode = opcode; - cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK); - cmd->arg1 = arg; - return next_cmd(cmd); -} - -static ipfw_insn * -fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr) -{ - ipfw_insn_ip *cmd = (ipfw_insn_ip *) cmd1; - - cmd->addr.s_addr = addr; - return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0); -} - -static ipfw_insn * -fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port) -{ - ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1; - - cmd->ports[0] = cmd->ports[1] = port; - return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0); -} - -static int -fill_rule(void *buf, int bufsize, int rulenum, - enum ipfw_opcodes action, int proto, - struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp) -{ - struct ip_fw *rule = (struct ip_fw *)buf; - ipfw_insn *cmd = (ipfw_insn *) rule->cmd; - - bzero(buf, bufsize); - rule->rulenum = rulenum; - - cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto); - cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr); - cmd = fill_one_port(cmd, O_IP_SRCPORT, sp); - cmd = fill_ip(cmd, O_IP_DST, da.s_addr); - cmd = fill_one_port(cmd, O_IP_DSTPORT, dp); - - rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd; - cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0); - - rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd; - - return ((char *)cmd - (char *)buf); -} - -#endif /* IPFW2 */ - -static void ClearAllFWHoles(struct libalias *la); - - -#define fw_setfield(la, field, num) \ -do { \ - (field)[(num) - la->fireWallBaseNum] = 1; \ -} /*lint -save -e717 */ while(0)/* lint -restore */ - -#define fw_clrfield(la, field, num) \ -do { \ - (field)[(num) - la->fireWallBaseNum] = 0; \ -} /*lint -save -e717 */ while(0)/* lint -restore */ - -#define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum]) - -static void -InitPunchFW(struct libalias *la) -{ - - la->fireWallField = malloc(la->fireWallNumNums); - if (la->fireWallField) { - memset(la->fireWallField, 0, la->fireWallNumNums); - if (la->fireWallFD < 0) { - la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); - } - ClearAllFWHoles(la); - la->fireWallActiveNum = la->fireWallBaseNum; - } -} - -static void -UninitPunchFW(struct libalias *la) -{ - ClearAllFWHoles(la); - if (la->fireWallFD >= 0) - close(la->fireWallFD); - la->fireWallFD = -1; - if (la->fireWallField) - free(la->fireWallField); - la->fireWallField = NULL; - la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW; -} - -/* Make a certain link go through the firewall */ -void -PunchFWHole(struct alias_link *lnk) -{ - struct libalias *la; - int r; /* Result code */ - struct ip_fw rule; /* On-the-fly built rule */ - int fwhole; /* Where to punch hole */ - - la = lnk->la; - -/* Don't do anything unless we are asked to */ - if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) || - la->fireWallFD < 0 || - lnk->link_type != LINK_TCP) - return; - - memset(&rule, 0, sizeof rule); - -/** Build rule **/ - - /* Find empty slot */ - for (fwhole = la->fireWallActiveNum; - fwhole < la->fireWallBaseNum + la->fireWallNumNums && - fw_tstfield(la, la->fireWallField, fwhole); - fwhole++); - if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) { - for (fwhole = la->fireWallBaseNum; - fwhole < la->fireWallActiveNum && - fw_tstfield(la, la->fireWallField, fwhole); - fwhole++); - if (fwhole == la->fireWallActiveNum) { - /* No rule point empty - we can't punch more holes. */ - la->fireWallActiveNum = la->fireWallBaseNum; -#ifdef DEBUG - fprintf(stderr, "libalias: Unable to create firewall hole!\n"); -#endif - return; - } - } - /* Start next search at next position */ - la->fireWallActiveNum = fwhole + 1; - - /* - * generate two rules of the form - * - * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole - * accept tcp from DAddr DPort to OAddr OPort - */ -#if IPFW2 - if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) { - u_int32_t rulebuf[255]; - int i; - - i = fill_rule(rulebuf, sizeof(rulebuf), fwhole, - O_ACCEPT, IPPROTO_TCP, - GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)), - GetDestAddress(lnk), ntohs(GetDestPort(lnk))); - r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i); - if (r) - err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)"); - - i = fill_rule(rulebuf, sizeof(rulebuf), fwhole, - O_ACCEPT, IPPROTO_TCP, - GetDestAddress(lnk), ntohs(GetDestPort(lnk)), - GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk))); - r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i); - if (r) - err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)"); - } -#else /* !IPFW2, old code to generate ipfw rule */ - - /* Build generic part of the two rules */ - rule.fw_number = fwhole; - IP_FW_SETNSRCP(&rule, 1); /* Number of source ports. */ - IP_FW_SETNDSTP(&rule, 1); /* Number of destination ports. */ - rule.fw_flg = IP_FW_F_ACCEPT | IP_FW_F_IN | IP_FW_F_OUT; - rule.fw_prot = IPPROTO_TCP; - rule.fw_smsk.s_addr = INADDR_BROADCAST; - rule.fw_dmsk.s_addr = INADDR_BROADCAST; - - /* Build and apply specific part of the rules */ - rule.fw_src = GetOriginalAddress(lnk); - rule.fw_dst = GetDestAddress(lnk); - rule.fw_uar.fw_pts[0] = ntohs(GetOriginalPort(lnk)); - rule.fw_uar.fw_pts[1] = ntohs(GetDestPort(lnk)); - - /* - * Skip non-bound links - XXX should not be strictly necessary, but - * seems to leave hole if not done. Leak of non-bound links? (Code - * should be left even if the problem is fixed - it is a clear - * optimization) - */ - if (rule.fw_uar.fw_pts[0] != 0 && rule.fw_uar.fw_pts[1] != 0) { - r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); -#ifdef DEBUG - if (r) - err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)"); -#endif - rule.fw_src = GetDestAddress(lnk); - rule.fw_dst = GetOriginalAddress(lnk); - rule.fw_uar.fw_pts[0] = ntohs(GetDestPort(lnk)); - rule.fw_uar.fw_pts[1] = ntohs(GetOriginalPort(lnk)); - r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); -#ifdef DEBUG - if (r) - err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)"); -#endif - } -#endif /* !IPFW2 */ -/* Indicate hole applied */ - lnk->data.tcp->fwhole = fwhole; - fw_setfield(la, la->fireWallField, fwhole); -} - -/* Remove a hole in a firewall associated with a particular alias - lnk. Calling this too often is harmless. */ -static void -ClearFWHole(struct alias_link *lnk) -{ - - struct libalias *la; - - la = lnk->la; - if (lnk->link_type == LINK_TCP) { - int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall - * hole? */ - struct ip_fw rule; - - if (fwhole < 0) - return; - - memset(&rule, 0, sizeof rule); /* useless for ipfw2 */ -#if IPFW2 - while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, - &fwhole, sizeof fwhole)); -#else /* !IPFW2 */ - rule.fw_number = fwhole; - while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, - &rule, sizeof rule)); -#endif /* !IPFW2 */ - fw_clrfield(la, la->fireWallField, fwhole); - lnk->data.tcp->fwhole = -1; - } -} - -/* Clear out the entire range dedicated to firewall holes. */ -static void -ClearAllFWHoles(struct libalias *la) -{ - struct ip_fw rule; /* On-the-fly built rule */ - int i; - - if (la->fireWallFD < 0) - return; - - memset(&rule, 0, sizeof rule); - for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) { -#if IPFW2 - int r = i; - - while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r)); -#else /* !IPFW2 */ - rule.fw_number = i; - while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule)); -#endif /* !IPFW2 */ - } - /* XXX: third arg correct here ? /phk */ - memset(la->fireWallField, 0, la->fireWallNumNums); -} - -#endif - -void -LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num) -{ -#ifndef NO_FW_PUNCH - la->fireWallBaseNum = base; - la->fireWallNumNums = num; -#endif -} - -void -LibAliasSetSkinnyPort(struct libalias *la, unsigned int port) -{ - la->skinnyPort = port; -} diff --git a/lib/libalias/alias_ftp.c b/lib/libalias/alias_ftp.c deleted file mode 100644 index b628528a0c1d..000000000000 --- a/lib/libalias/alias_ftp.c +++ /dev/null @@ -1,675 +0,0 @@ -/*- - * Copyright (c) 2001 Charles Mott - * 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 -__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 -#include -#include -#include -#include -#include -#include -#include - -#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 - } -} diff --git a/lib/libalias/alias_irc.c b/lib/libalias/alias_irc.c deleted file mode 100644 index 66106fa35112..000000000000 --- a/lib/libalias/alias_irc.c +++ /dev/null @@ -1,386 +0,0 @@ -/*- - * Copyright (c) 2001 Charles Mott - * 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 -__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 (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 -#include -#include -#include -#include -#include -#include -#include -#include - -#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. - */ diff --git a/lib/libalias/alias_local.h b/lib/libalias/alias_local.h deleted file mode 100644 index 67947da81853..000000000000 --- a/lib/libalias/alias_local.h +++ /dev/null @@ -1,355 +0,0 @@ -/*- - * Copyright (c) 2001 Charles Mott - * 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) - * - * - */ - -#ifndef _ALIAS_LOCAL_H_ -#define _ALIAS_LOCAL_H_ - -#include - -/* 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_ */ diff --git a/lib/libalias/alias_nbt.c b/lib/libalias/alias_nbt.c deleted file mode 100644 index b51abd1c5da5..000000000000 --- a/lib/libalias/alias_nbt.c +++ /dev/null @@ -1,722 +0,0 @@ -/*- - * Written by Atsushi Murai - * 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 -__FBSDID("$FreeBSD$"); - -/* - alias_nbt.c performs special processing for NetBios over TCP/IP - sessions by UDP. - - Initial version: May, 1998 (Atsushi Murai ) - - See HISTORY file for record of revisions. -*/ - -/* Includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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); -} diff --git a/lib/libalias/alias_old.c b/lib/libalias/alias_old.c deleted file mode 100644 index 089ecef55aee..000000000000 --- a/lib/libalias/alias_old.c +++ /dev/null @@ -1,205 +0,0 @@ -/*- - * Copyright (c) 2004 Poul-Henning Kamp - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#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); -} diff --git a/lib/libalias/alias_pptp.c b/lib/libalias/alias_pptp.c deleted file mode 100644 index 05722b10813d..000000000000 --- a/lib/libalias/alias_pptp.c +++ /dev/null @@ -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 - */ - -#include -__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 -#include -#include -#include -#include - -#include - -#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); -} diff --git a/lib/libalias/alias_proxy.c b/lib/libalias/alias_proxy.c deleted file mode 100644 index e0e1c059ed68..000000000000 --- a/lib/libalias/alias_proxy.c +++ /dev/null @@ -1,812 +0,0 @@ -/*- - * Copyright (c) 2001 Charles Mott - * 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 -__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 -#include -#include -#include -#include - -#include -#include - -/* BSD IPV4 includes */ -#include -#include -#include -#include - -#include - -#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 [:] - * [port ] - * [rule n] - * [proto tcp|udp] - * [src [/n]] - * [dst [/n]] - * [type encode_tcp_stream|encode_ip_hdr|no_encode] - * - * delete - * - * 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); -} diff --git a/lib/libalias/alias_skinny.c b/lib/libalias/alias_skinny.c deleted file mode 100644 index d1e4a1469377..000000000000 --- a/lib/libalias/alias_skinny.c +++ /dev/null @@ -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 - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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); - } -} diff --git a/lib/libalias/alias_smedia.c b/lib/libalias/alias_smedia.c deleted file mode 100644 index 888937c9f241..000000000000 --- a/lib/libalias/alias_smedia.c +++ /dev/null @@ -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 - * - * 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 - * Junichi SATOH - * - */ - -#include -__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 -#include -#include -#include -#include -#include -#include -#include - -#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); - - } - } - } - } -} diff --git a/lib/libalias/alias_util.c b/lib/libalias/alias_util.c deleted file mode 100644 index 687168e830b7..000000000000 --- a/lib/libalias/alias_util.c +++ /dev/null @@ -1,164 +0,0 @@ -/*- - * Copyright (c) 2001 Charles Mott - * 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 -__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 -#include -#include -#include -#include -#include - -#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; - } -} diff --git a/lib/libalias/libalias.3 b/lib/libalias/libalias.3 deleted file mode 100644 index d429d7d0bfbb..000000000000 --- a/lib/libalias/libalias.3 +++ /dev/null @@ -1,1018 +0,0 @@ -.\"- -.\" Copyright (c) 2001 Charles Mott -.\" 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$ -.\" -.Dd January 17, 2004 -.Dt LIBALIAS 3 -.Os -.Sh NAME -.Nm libalias -.Nd packet aliasing library for masquerading and network address translation -.Sh SYNOPSIS -.In sys/types.h -.In netinet/in.h -.In alias.h -.Pp -Function prototypes are given in the main body of the text. -.Sh DESCRIPTION -The -.Nm -library is a collection of functions for aliasing and de-aliasing of IP -packets, intended for masquerading and network address translation (NAT). -.Sh INTRODUCTION -This library is a moderately portable set of functions designed to assist -in the process of IP masquerading and network address translation. -Outgoing packets from a local network with unregistered IP addresses can -be aliased to appear as if they came from an accessible IP address. -Incoming packets are then de-aliased so that they are sent to the correct -machine on the local network. -.Pp -A certain amount of flexibility is built into the packet aliasing engine. -In the simplest mode of operation, a many-to-one address mapping takes -place between local network and the packet aliasing host. -This is known as IP masquerading. -In addition, one-to-one mappings between local and public addresses can -also be implemented, which is known as static NAT. -In between these extremes, different groups of private addresses can be -linked to different public addresses, comprising several distinct -many-to-one mappings. -Also, a given public address and port can be statically redirected to a -private address/port. -.Pp -The packet aliasing engine was designed to operate in user space outside -of the kernel, without any access to private kernel data structure, but -the source code can also be ported to a kernel environment. -.Sh INITIALIZATION AND CONTROL -One special function, -.Fn LibAliasInit , -must always be called before any packet handling may be performed and -the returned instance pointer passed to all the other functions. -Normally, the -.Fn LibAliasSetAddress -function is called afterwards, to set the default aliasing address. -In addition, the operating mode of the packet aliasing engine can be -customized by calling -.Fn LibAliasSetMode . -.Pp -.Ft "struct libalias *" -.Fn LibAliasInit "struct libalias *" -.Bd -ragged -offset indent -This function is used to initialize -internal data structures. -When called the first time, a -.Dv NULL -pointer should be passed as an argument. -The following mode bits are always set after calling -.Fn LibAliasInit . -See the description of -.Fn LibAliasSetMode -below for the meaning of these mode bits. -.Pp -.Bl -item -offset indent -compact -.It -.Dv PKT_ALIAS_SAME_PORTS -.It -.Dv PKT_ALIAS_USE_SOCKETS -.It -.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE -.El -.Pp -This function will always return the packet aliasing engine to the same -initial state. -The -.Fn LibAliasSetAddress -function is normally called afterwards, and any desired changes from the -default mode bits listed above require a call to -.Fn LibAliasSetMode . -.Pp -It is mandatory that this function be called at the beginning of a program -prior to any packet handling. -.Ed -.Pp -.Ft void -.Fn LibAliasUninit "struct libalias *" -.Bd -ragged -offset indent -This function has no return value and is used to clear any -resources attached to internal data structures. -.Pp -This functions should be called when a program stops using the aliasing -engine; it does, amongst other things, clear out any firewall holes. -To provide backwards compatibility and extra security, it is added to -the -.Xr atexit 3 -chain by -.Fn LibAliasInit . -.Ed -.Pp -.Ft void -.Fn LibAliasSetAddress "struct libalias *" "struct in_addr addr" -.Bd -ragged -offset indent -This function sets the source address to which outgoing packets from the -local area network are aliased. -All outgoing packets are re-mapped to this address unless overridden by a -static address mapping established by -.Fn LibAliasRedirectAddr . -If this function is not called, and no static rules match, an outgoing -packet retains its source address. -.Pp -If the -.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE -mode bit is set (the default mode of operation), then the internal aliasing -link tables will be reset any time the aliasing address changes. -This is useful for interfaces such as -.Xr ppp 8 , -where the IP -address may or may not change on successive dial-up attempts. -.Pp -If the -.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE -mode bit is set to zero, this function can also be used to dynamically change -the aliasing address on a packet to packet basis (it is a low overhead call). -.Pp -It is mandatory that this function be called prior to any packet handling. -.Ed -.Pp -.Ft unsigned int -.Fn LibAliasSetMode "struct libalias *" "unsigned int flags" "unsigned int mask" -.Bd -ragged -offset indent -This function sets or clears mode bits -according to the value of -.Fa flags . -Only bits marked in -.Fa mask -are affected. -The following mode bits are defined in -.In alias.h : -.Bl -tag -width indent -.It Dv PKT_ALIAS_LOG -Enables logging into -.Pa /var/log/alias.log . -Each time an aliasing link is created or deleted, the log file is appended -with the current number of ICMP, TCP and UDP links. -Mainly useful for debugging when the log file is viewed continuously with -.Xr tail 1 . -.It Dv PKT_ALIAS_DENY_INCOMING -If this mode bit is set, all incoming packets associated with new TCP -connections or new UDP transactions will be marked for being ignored -.Fn ( LibAliasIn -returns -.Dv PKT_ALIAS_IGNORED -code) -by the calling program. -Response packets to connections or transactions initiated from the packet -aliasing host or local network will be unaffected. -This mode bit is useful for implementing a one-way firewall. -.It Dv PKT_ALIAS_SAME_PORTS -If this mode bit is set, the packet aliasing engine will attempt to leave -the alias port numbers unchanged from the actual local port numbers. -This can be done as long as the quintuple (proto, alias addr, alias port, -remote addr, remote port) is unique. -If a conflict exists, a new aliasing port number is chosen even if this -mode bit is set. -.It Dv PKT_ALIAS_USE_SOCKETS -This bit should be set when the packet aliasing host originates network -traffic as well as forwards it. -When the packet aliasing host is waiting for a connection from an unknown -host address or unknown port number (e.g.\& an FTP data connection), this -mode bit specifies that a socket be allocated as a place holder to prevent -port conflicts. -Once a connection is established, usually within a minute or so, the socket -is closed. -.It Dv PKT_ALIAS_UNREGISTERED_ONLY -If this mode bit is set, traffic on the local network which does not -originate from unregistered address spaces will be ignored. -Standard Class A, B and C unregistered addresses are: -.Bd -literal -offset indent -10.0.0.0 -> 10.255.255.255 (Class A subnet) -172.16.0.0 -> 172.31.255.255 (Class B subnets) -192.168.0.0 -> 192.168.255.255 (Class C subnets) -.Ed -.Pp -This option is useful in the case that packet aliasing host has both -registered and unregistered subnets on different interfaces. -The registered subnet is fully accessible to the outside world, so traffic -from it does not need to be passed through the packet aliasing engine. -.It Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE -When this mode bit is set and -.Fn LibAliasSetAddress -is called to change the aliasing address, the internal link table of the -packet aliasing engine will be cleared. -This operating mode is useful for -.Xr ppp 8 -links where the interface address can sometimes change or remain the same -between dial-up attempts. -If this mode bit is not set, the link table will never be reset in the event -of an address change. -.It Dv PKT_ALIAS_PUNCH_FW -This option makes -.Nm -`punch holes' in an -.Xr ipfirewall 4 -based firewall for FTP/IRC DCC connections. -The holes punched are bound by from/to IP address and port; it will not be -possible to use a hole for another connection. -A hole is removed when the connection that uses it dies. -To cater to unexpected death of a program using -.Nm -(e.g.\& kill -9), -changing the state of the flag will clear the entire firewall range -allocated for holes. -This will also happen on the initial call to -.Fn LibAliasSetFWBase . -This call must happen prior to setting this flag. -.It Dv PKT_ALIAS_REVERSE -This option makes -.Nm -reverse the way it handles incoming and outgoing packets, allowing it -to be fed with data that passes through the internal interface rather -than the external one. -.It Dv PKT_ALIAS_PROXY_ONLY -This option tells -.Nm -to obey transparent proxy rules only. -Normal packet aliasing is not performed. -See -.Fn LibAliasProxyRule -below for details. -.El -.Ed -.Pp -.Ft void -.Fn LibAliasSetFWBase "struct libalias *" "unsigned int base" "unsigned int num" -.Bd -ragged -offset indent -Set firewall range allocated for punching firewall holes (with the -.Dv PKT_ALIAS_PUNCH_FW -flag). -The range will be cleared for all rules on initialization. -.Ed -.Pp -.Ft void -.Fn LibAliasSkinnyPort "struct libalias *" "unsigned int port" -.Bd -ragged -offset indent -Set the TCP port used by the Skinny Station protocol. -Skinny is used by Cisco IP phones to communicate with -Cisco Call Managers to set up voice over IP calls. -If this is not set, Skinny aliasing will not be done. -The typical port used by Skinny is 2000. -.Ed -.Sh PACKET HANDLING -The packet handling functions are used to modify incoming (remote to local) -and outgoing (local to remote) packets. -The calling program is responsible for receiving and sending packets via -network interfaces. -.Pp -Along with -.Fn LibAliasInit -and -.Fn LibAliasSetAddress , -the two packet handling functions, -.Fn LibAliasIn -and -.Fn LibAliasOut , -comprise minimal set of functions needed for a basic IP masquerading -implementation. -.Pp -.Ft int -.Fn LibAliasIn "struct libalias *" "char *buffer" "int maxpacketsize" -.Bd -ragged -offset indent -An incoming packet coming from a remote machine to the local network is -de-aliased by this function. -The IP packet is pointed to by -.Fa buffer , -and -.Fa maxpacketsize -indicates the size of the data structure containing the packet and should -be at least as large as the actual packet size. -.Pp -Return codes: -.Bl -tag -width indent -.It Dv PKT_ALIAS_OK -The packet aliasing process was successful. -.It Dv PKT_ALIAS_IGNORED -The packet was ignored and not de-aliased. -This can happen if the protocol is unrecognized, possibly an ICMP message -type is not handled or if incoming packets for new connections are being -ignored (if -.Dv PKT_ALIAS_DENY_INCOMING -mode bit was set by -.Fn LibAliasSetMode ) . -.It Dv PKT_ALIAS_UNRESOLVED_FRAGMENT -This is returned when a fragment cannot be resolved because the header -fragment has not been sent yet. -In this situation, fragments must be saved with -.Fn LibAliasSaveFragment -until a header fragment is found. -.It Dv PKT_ALIAS_FOUND_HEADER_FRAGMENT -The packet aliasing process was successful, and a header fragment was found. -This is a signal to retrieve any unresolved fragments with -.Fn LibAliasGetFragment -and de-alias them with -.Fn LibAliasFragmentIn . -.It Dv PKT_ALIAS_ERROR -An internal error within the packet aliasing engine occurred. -.El -.Ed -.Pp -.Ft int -.Fn LibAliasOut "struct libalias *" "char *buffer" "int maxpacketsize" -.Bd -ragged -offset indent -An outgoing packet coming from the local network to a remote machine is -aliased by this function. -The IP packet is pointed to by -.Fa buffer , -and -.Fa maxpacketsize -indicates the maximum packet size permissible should the packet length be -changed. -IP encoding protocols place address and port information in the encapsulated -data stream which has to be modified and can account for changes in packet -length. -Well known examples of such protocols are FTP and IRC DCC. -.Pp -Return codes: -.Bl -tag -width indent -.It Dv PKT_ALIAS_OK -The packet aliasing process was successful. -.It Dv PKT_ALIAS_IGNORED -The packet was ignored and not aliased. -This can happen if the protocol is unrecognized, or possibly an ICMP message -type is not handled. -.It Dv PKT_ALIAS_ERROR -An internal error within the packet aliasing engine occurred. -.El -.Ed -.Sh PORT AND ADDRESS REDIRECTION -The functions described in this section allow machines on the local network -to be accessible in some degree to new incoming connections from the external -network. -Individual ports can be re-mapped or static network address translations can -be designated. -.Pp -.Ft struct alias_link * -.Fo LibAliasRedirectPort -.Fa "struct libalias *" -.Fa "struct in_addr local_addr" -.Fa "u_short local_port" -.Fa "struct in_addr remote_addr" -.Fa "u_short remote_port" -.Fa "struct in_addr alias_addr" -.Fa "u_short alias_port" -.Fa "u_char proto" -.Fc -.Bd -ragged -offset indent -This function specifies that traffic from a given remote address/port to -an alias address/port be redirected to a specified local address/port. -The parameter -.Fa proto -can be either -.Dv IPPROTO_TCP -or -.Dv IPPROTO_UDP , -as defined in -.In netinet/in.h . -.Pp -If -.Fa local_addr -or -.Fa alias_addr -is zero, this indicates that the packet aliasing address as established -by -.Fn LibAliasSetAddress -is to be used. -Even if -.Fn LibAliasSetAddress -is called to change the address after -.Fn LibAliasRedirectPort -is called, a zero reference will track this change. -.Pp -If the link is further set up to operate for a load sharing, then -.Fa local_addr -and -.Fa local_port -are ignored, and are selected dynamically from the server pool, as described in -.Fn LibAliasAddServer -below. -.Pp -If -.Fa remote_addr -is zero, this indicates to redirect packets from any remote address. -Likewise, if -.Fa remote_port -is zero, this indicates to redirect packets originating from any remote -port number. -Almost always, the remote port specification will be zero, but non-zero -remote addresses can sometimes be useful for firewalling. -If two calls to -.Fn LibAliasRedirectPort -overlap in their address/port specifications, then the most recent call -will have precedence. -.Pp -This function returns a pointer which can subsequently be used by -.Fn LibAliasRedirectDelete . -If -.Dv NULL -is returned, then the function call did not complete successfully. -.Pp -All port numbers should be in network address byte order, so it is necessary -to use -.Xr htons 3 -to convert these parameters from internally readable numbers to network byte -order. -Addresses are also in network byte order, which is implicit in the use of the -.Fa struct in_addr -data type. -.Ed -.Pp -.Ft struct alias_link * -.Fo LibAliasRedirectAddr -.Fa "struct libalias *" -.Fa "struct in_addr local_addr" -.Fa "struct in_addr alias_addr" -.Fc -.Bd -ragged -offset indent -This function designates that all incoming traffic to -.Fa alias_addr -be redirected to -.Fa local_addr . -Similarly, all outgoing traffic from -.Fa local_addr -is aliased to -.Fa alias_addr . -.Pp -If -.Fa local_addr -or -.Fa alias_addr -is zero, this indicates that the packet aliasing address as established by -.Fn LibAliasSetAddress -is to be used. -Even if -.Fn LibAliasSetAddress -is called to change the address after -.Fn LibAliasRedirectAddr -is called, a zero reference will track this change. -.Pp -If the link is further set up to operate for a load sharing, then -.Fa local_addr -is ignored, and is selected dynamically from the server pool, as described in -.Fn LibAliasAddServer -below. -.Pp -If subsequent calls to -.Fn LibAliasRedirectAddr -use the same aliasing address, all new incoming traffic to this aliasing -address will be redirected to the local address made in the last function -call. -New traffic generated by any of the local machines, designated in the -several function calls, will be aliased to the same address. -Consider the following example: -.Bd -literal -offset indent -LibAliasRedirectAddr(la, inet_aton("192.168.0.2"), - inet_aton("141.221.254.101")); -LibAliasRedirectAddr(la, inet_aton("192.168.0.3"), - inet_aton("141.221.254.101")); -LibAliasRedirectAddr(la, inet_aton("192.168.0.4"), - inet_aton("141.221.254.101")); -.Ed -.Pp -Any outgoing connections such as -.Xr telnet 1 -or -.Xr ftp 1 -from 192.168.0.2, 192.168.0.3 and 192.168.0.4 will appear to come from -141.221.254.101. -Any incoming connections to 141.221.254.101 will be directed to 192.168.0.4. -.Pp -Any calls to -.Fn LibAliasRedirectPort -will have precedence over address mappings designated by -.Fn LibAliasRedirectAddr . -.Pp -This function returns a pointer which can subsequently be used by -.Fn LibAliasRedirectDelete . -If -.Dv NULL -is returned, then the function call did not complete successfully. -.Ed -.Pp -.Ft int -.Fo LibAliasAddServer -.Fa "struct libalias *" -.Fa "struct alias_link *link" -.Fa "struct in_addr addr" -.Fa "u_short port" -.Fc -.Bd -ragged -offset indent -This function sets the -.Fa link -up for Load Sharing using IP Network Address Translation (RFC 2391, LSNAT). -LSNAT operates as follows. -A client attempts to access a server by using the server virtual address. -The LSNAT router transparently redirects the request to one of the hosts -in server pool, selected using a real-time load sharing algorithm. -Multiple sessions may be initiated from the same client, and each session -could be directed to a different host based on load balance across server -pool hosts at the time. -If load share is desired for just a few specific services, the configuration -on LSNAT could be defined to restrict load share for just the services -desired. -.Pp -Currently, only the simplest selection algorithm is implemented, where a -host is selected on a round-robin basis only, without regard to load on -the host. -.Pp -First, the -.Fa link -is created by either -.Fn LibAliasRedirectPort -or -.Fn LibAliasRedirectAddr . -Then, -.Fn LibAliasAddServer -is called multiple times to add entries to the -.Fa link Ns 's -server pool. -.Pp -For links created with -.Fn LibAliasRedirectAddr , -the -.Fa port -argument is ignored and could have any value, e.g.\& htons(~0). -.Pp -This function returns 0 on success, \-1 otherwise. -.Ed -.Pp -.Ft int -.Fn LibAliasRedirectDynamic "struct libalias *" "struct alias_link *link" -.Bd -ragged -offset indent -This function marks the specified static redirect rule entered by -.Fn LibAliasRedirectPort -as dynamic. -This can be used to e.g.\& dynamically redirect a single TCP connection, -after which the rule is removed. -Only fully specified links can be made dynamic. -(See the -.Sx STATIC AND DYNAMIC LINKS -and -.Sx PARTIALLY SPECIFIED ALIASING LINKS -sections below for a definition of static vs.\& dynamic, -and partially vs.\& fully specified links.) -.Pp -This function returns 0 on success, \-1 otherwise. -.Ed -.Pp -.Ft void -.Fn LibAliasRedirectDelete "struct libalias *" "struct alias_link *link" -.Bd -ragged -offset indent -This function will delete a specific static redirect rule entered by -.Fn LibAliasRedirectPort -or -.Fn LibAliasRedirectAddr . -The parameter -.Fa link -is the pointer returned by either of the redirection functions. -If an invalid pointer is passed to -.Fn LibAliasRedirectDelete , -then a program crash or unpredictable operation could result, so it is -necessary to be careful using this function. -.Ed -.Pp -.Ft int -.Fn LibAliasProxyRule "struct libalias *" "const char *cmd" -.Bd -ragged -offset indent -The passed -.Fa cmd -string consists of one or more pairs of words. -The first word in each pair is a token and the second is the value that -should be applied for that token. -Tokens and their argument types are as follows: -.Bl -tag -width indent -.It Cm type encode_ip_hdr | encode_tcp_stream | no_encode -In order to support transparent proxying, it is necessary to somehow -pass the original address and port information into the new destination -server. -If -.Cm encode_ip_hdr -is specified, the original destination address and port are passed -as an extra IP option. -If -.Cm encode_tcp_stream -is specified, the original destination address and port are passed -as the first piece of data in the TCP stream in the format -.Dq Li DEST Ar IP port . -.It Cm port Ar portnum -Only packets with the destination port -.Ar portnum -are proxied. -.It Cm server Ar host Ns Op : Ns Ar portnum -This specifies the -.Ar host -and -.Ar portnum -that the data is to be redirected to. -.Ar host -must be an IP address rather than a DNS host name. -If -.Ar portnum -is not specified, the destination port number is not changed. -.Pp -The -.Ar server -specification is mandatory unless the -.Cm delete -command is being used. -.It Cm rule Ar index -Normally, each call to -.Fn LibAliasProxyRule -inserts the next rule at the start of a linear list of rules. -If an -.Ar index -is specified, the new rule will be checked after all rules with lower -indices. -Calls to -.Fn LibAliasProxyRule -that do not specify a rule are assigned rule 0. -.It Cm delete Ar index -This token and its argument MUST NOT be used with any other tokens. -When used, all existing rules with the given -.Ar index -are deleted. -.It Cm proto tcp | udp -If specified, only packets of the given protocol type are matched. -.It Cm src Ar IP Ns Op / Ns Ar bits -If specified, only packets with a source address matching the given -.Ar IP -are matched. -If -.Ar bits -is also specified, then the first -.Ar bits -bits of -.Ar IP -are taken as a network specification, and all IP addresses from that -network will be matched. -.It Cm dst Ar IP Ns Op / Ns Ar bits -If specified, only packets with a destination address matching the given -.Ar IP -are matched. -If -.Ar bits -is also specified, then the first -.Ar bits -bits of -.Ar IP -are taken as a network specification, and all IP addresses from that -network will be matched. -.El -.Pp -This function is usually used to redirect outgoing connections for -internal machines that are not permitted certain types of internet -access, or to restrict access to certain external machines. -.Ed -.Pp -.Ft struct alias_link * -.Fo LibAliasRedirectProto -.Fa "struct libalias *" -.Fa "struct in_addr local_addr" -.Fa "struct in_addr remote_addr" -.Fa "struct in_addr alias_addr" -.Fa "u_char proto" -.Fc -.Bd -ragged -offset indent -This function specifies that any IP packet with protocol number of -.Fa proto -from a given remote address to an alias address be -redirected to a specified local address. -.Pp -If -.Fa local_addr -or -.Fa alias_addr -is zero, this indicates that the packet aliasing address as established -by -.Fn LibAliasSetAddress -is to be used. -Even if -.Fn LibAliasSetAddress -is called to change the address after -.Fn LibAliasRedirectProto -is called, a zero reference will track this change. -.Pp -If -.Fa remote_addr -is zero, this indicates to redirect packets from any remote address. -Non-zero remote addresses can sometimes be useful for firewalling. -.Pp -If two calls to -.Fn LibAliasRedirectProto -overlap in their address specifications, then the most recent call -will have precedence. -.Pp -This function returns a pointer which can subsequently be used by -.Fn LibAliasRedirectDelete . -If -.Dv NULL -is returned, then the function call did not complete successfully. -.Ed -.Sh FRAGMENT HANDLING -The functions in this section are used to deal with incoming fragments. -.Pp -Outgoing fragments are handled within -.Fn LibAliasOut -by changing the address according to any applicable mapping set by -.Fn LibAliasRedirectAddr , -or the default aliasing address set by -.Fn LibAliasSetAddress . -.Pp -Incoming fragments are handled in one of two ways. -If the header of a fragmented IP packet has already been seen, then all -subsequent fragments will be re-mapped in the same manner the header -fragment was. -Fragments which arrive before the header are saved and then retrieved -once the header fragment has been resolved. -.Pp -.Ft int -.Fn LibAliasSaveFragment "struct libalias *" "char *ptr" -.Bd -ragged -offset indent -When -.Fn LibAliasIn -returns -.Dv PKT_ALIAS_UNRESOLVED_FRAGMENT , -this function can be used to save the pointer to the unresolved fragment. -.Pp -It is implicitly assumed that -.Fa ptr -points to a block of memory allocated by -.Xr malloc 3 . -If the fragment is never resolved, the packet aliasing engine will -automatically free the memory after a timeout period. -[Eventually this function should be modified so that a callback function -for freeing memory is passed as an argument.] -.Pp -This function returns -.Dv PKT_ALIAS_OK -if it was successful and -.Dv PKT_ALIAS_ERROR -if there was an error. -.Ed -.Pp -.Ft char * -.Fn LibAliasGetFragment "struct libalias *" "char *buffer" -.Bd -ragged -offset indent -This function can be used to retrieve fragment pointers saved by -.Fn LibAliasSaveFragment . -The IP header fragment pointed to by -.Fa buffer -is the header fragment indicated when -.Fn LibAliasIn -returns -.Dv PKT_ALIAS_FOUND_HEADER_FRAGMENT . -Once a fragment pointer is retrieved, it becomes the calling program's -responsibility to free the dynamically allocated memory for the fragment. -.Pp -The -.Fn LibAliasGetFragment -function can be called sequentially until there are no more fragments -available, at which time it returns -.Dv NULL . -.Ed -.Pp -.Ft void -.Fn LibAliasFragmentIn "struct libalias *" "char *header" "char *fragment" -.Bd -ragged -offset indent -When a fragment is retrieved with -.Fn LibAliasGetFragment , -it can then be de-aliased with a call to -.Fn LibAliasFragmentIn . -The -.Fa header -argument is the pointer to a header fragment used as a template, and -.Fa fragment -is the pointer to the packet to be de-aliased. -.Ed -.Sh MISCELLANEOUS FUNCTIONS -.Ft void -.Fn LibAliasSetTarget "struct libalias *" "struct in_addr addr" -.Bd -ragged -offset indent -When an incoming packet not associated with any pre-existing aliasing link -arrives at the host machine, it will be sent to the address indicated by a -call to -.Fn LibAliasSetTarget . -.Pp -If this function is called with an -.Dv INADDR_NONE -address argument, then all new incoming packets go to the address set by -.Fn LibAliasSetAddress . -.Pp -If this function is not called, or is called with an -.Dv INADDR_ANY -address argument, then all new incoming packets go to the address specified -in the packet. -This allows external machines to talk directly to internal machines if they -can route packets to the machine in question. -.Ed -.Pp -.Ft int -.Fn LibAliasCheckNewLink void -.Bd -ragged -offset indent -This function returns a non-zero value when a new aliasing link is created. -In circumstances where incoming traffic is being sequentially sent to -different local servers, this function can be used to trigger when -.Fn LibAliasSetTarget -is called to change the default target address. -.Ed -.Pp -.Ft u_short -.Fn LibAliasInternetChecksum "struct libalias *" "u_short *buffer" "int nbytes" -.Bd -ragged -offset indent -This is a utility function that does not seem to be available elsewhere and -is included as a convenience. -It computes the internet checksum, which is used in both IP and -protocol-specific headers (TCP, UDP, ICMP). -.Pp -The -.Fa buffer -argument points to the data block to be checksummed, and -.Fa nbytes -is the number of bytes. -The 16-bit checksum field should be zeroed before computing the checksum. -.Pp -Checksums can also be verified by operating on a block of data including -its checksum. -If the checksum is valid, -.Fn LibAliasInternetChecksum -will return zero. -.Ed -.Pp -.Ft int -.Fn LibAliasUnaliasOut "struct libalias *" "char *buffer" "int maxpacketsize" -.Bd -ragged -offset indent -An outgoing packet, which has already been aliased, -has its private address/port information restored by this function. -The IP packet is pointed to by -.Fa buffer , -and -.Fa maxpacketsize -is provided for error checking purposes. -This function can be used if an already-aliased packet needs to have its -original IP header restored for further processing (e.g.\& logging). -.Ed -.Sh AUTHORS -.An Charles Mott Aq cm@linktel.net , -versions 1.0 - 1.8, 2.0 - 2.4. -.An Eivind Eklund Aq eivind@FreeBSD.org , -versions 1.8b, 1.9 and 2.5. -Added IRC DCC support as well as contributing a number of architectural -improvements; added the firewall bypass for FTP/IRC DCC. -.An Erik Salander Aq erik@whistle.com -added support for PPTP and RTSP. -.An Junichi Satoh Aq junichi@junichi.org -added support for RTSP/PNA. -.An Ruslan Ermilov Aq ru@FreeBSD.org -added support for PPTP and LSNAT as well as general hacking. -.Sh ACKNOWLEDGMENTS -Listed below, in approximate chronological order, are individuals who -have provided valuable comments and/or debugging assistance. -.Pp -.Bd -ragged -offset indent -.An -split -.An Gary Roberts -.An Tom Torrance -.An Reto Burkhalter -.An Martin Renters -.An Brian Somers -.An Paul Traina -.An Ari Suutari -.An Dave Remien -.An J. Fortes -.An Andrzej Bialecki -.An Gordon Burditt -.Ed -.Sh CONCEPTUAL BACKGROUND -This section is intended for those who are planning to modify the source -code or want to create somewhat esoteric applications using the packet -aliasing functions. -.Pp -The conceptual framework under which the packet aliasing engine operates -is described here. -Central to the discussion is the idea of an -.Em aliasing link -which describes the relationship for a given packet transaction between -the local machine, aliased identity and remote machine. -It is discussed how such links come into existence and are destroyed. -.Ss ALIASING LINKS -There is a notion of an -.Em aliasing link , -which is a 7-tuple describing a specific translation: -.Bd -literal -offset indent -(local addr, local port, alias addr, alias port, - remote addr, remote port, protocol) -.Ed -.Pp -Outgoing packets have the local address and port number replaced with the -alias address and port number. -Incoming packets undergo the reverse process. -The packet aliasing engine attempts to match packets against an internal -table of aliasing links to determine how to modify a given IP packet. -Both the IP header and protocol dependent headers are modified as necessary. -Aliasing links are created and deleted as necessary according to network -traffic. -.Pp -Protocols can be TCP, UDP or even ICMP in certain circumstances. -(Some types of ICMP packets can be aliased according to sequence or ID -number which acts as an equivalent port number for identifying how -individual packets should be handled.) -.Pp -Each aliasing link must have a unique combination of the following five -quantities: alias address/port, remote address/port and protocol. -This ensures that several machines on a local network can share the -same aliasing IP address. -In cases where conflicts might arise, the aliasing port is chosen so that -uniqueness is maintained. -.Ss STATIC AND DYNAMIC LINKS -Aliasing links can either be static or dynamic. -Static links persist indefinitely and represent fixed rules for translating -IP packets. -Dynamic links come into existence for a specific TCP connection or UDP -transaction or ICMP ECHO sequence. -For the case of TCP, the connection can be monitored to see when the -associated aliasing link should be deleted. -Aliasing links for UDP transactions (and ICMP ECHO and TIMESTAMP requests) -work on a simple timeout rule. -When no activity is observed on a dynamic link for a certain amount of time -it is automatically deleted. -Timeout rules also apply to TCP connections which do not open or close -properly. -.Ss PARTIALLY SPECIFIED ALIASING LINKS -Aliasing links can be partially specified, meaning that the remote address -and/or remote port are unknown. -In this case, when a packet matching the incomplete specification is found, -a fully specified dynamic link is created. -If the original partially specified link is dynamic, it will be deleted -after the fully specified link is created, otherwise it will persist. -.Pp -For instance, a partially specified link might be -.Bd -literal -offset indent -(192.168.0.4, 23, 204.228.203.215, 8066, 0, 0, tcp) -.Ed -.Pp -The zeros denote unspecified components for the remote address and port. -If this link were static it would have the effect of redirecting all -incoming traffic from port 8066 of 204.228.203.215 to port 23 (telnet) -of machine 192.168.0.4 on the local network. -Each individual telnet connection would initiate the creation of a distinct -dynamic link. -.Ss DYNAMIC LINK CREATION -In addition to aliasing links, there are also address mappings that can be -stored within the internal data table of the packet aliasing mechanism. -.Bd -literal -offset indent -(local addr, alias addr) -.Ed -.Pp -Address mappings are searched when creating new dynamic links. -.Pp -All outgoing packets from the local network automatically create a dynamic -link if they do not match an already existing fully specified link. -If an address mapping exists for the outgoing packet, this determines -the alias address to be used. -If no mapping exists, then a default address, usually the address of the -packet aliasing host, is used. -If necessary, this default address can be changed as often as each individual -packet arrives. -.Pp -The aliasing port number is determined such that the new dynamic link does -not conflict with any existing links. -In the default operating mode, the packet aliasing engine attempts to set -the aliasing port equal to the local port number. -If this results in a conflict, then port numbers are randomly chosen until -a unique aliasing link can be established. -In an alternate operating mode, the first choice of an aliasing port is also -random and unrelated to the local port number. -.Sh BUGS -PPTP aliasing does not work when more than one internal client -connects to the same external server at the same time, because -PPTP requires a single TCP control connection to be established -between any two IP addresses.