aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorcvs2svn <cvs2svn@FreeBSD.org>1999-01-21 00:55:31 +0000
committercvs2svn <cvs2svn@FreeBSD.org>1999-01-21 00:55:31 +0000
commit4b4d01da6f07f7754ff6a6e4f5223e9f0984d1a6 (patch)
tree9ef395ed57f97b5613d996298d19e60c8e518010 /sys/netinet
parent99af619cb2f1dac921ef1dd9fe5661503220f524 (diff)
This commit was manufactured by cvs2svn to create branch 'RELENG_3'.
Notes
Notes: svn path=/stable/3/; revision=42951
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/libalias/HISTORY129
-rw-r--r--sys/netinet/libalias/Makefile15
-rw-r--r--sys/netinet/libalias/alias.c1165
-rw-r--r--sys/netinet/libalias/alias.h173
-rw-r--r--sys/netinet/libalias/alias_cuseeme.c120
-rw-r--r--sys/netinet/libalias/alias_db.c2241
-rw-r--r--sys/netinet/libalias/alias_ftp.c227
-rw-r--r--sys/netinet/libalias/alias_irc.c316
-rw-r--r--sys/netinet/libalias/alias_local.h107
-rw-r--r--sys/netinet/libalias/alias_nbt.c713
-rw-r--r--sys/netinet/libalias/alias_old.c77
-rw-r--r--sys/netinet/libalias/alias_util.c137
-rw-r--r--sys/netinet/libalias/libalias.3768
-rw-r--r--sys/netinet/tcp_reass.c2231
-rw-r--r--sys/netinet/tcp_timewait.c751
15 files changed, 0 insertions, 9170 deletions
diff --git a/sys/netinet/libalias/HISTORY b/sys/netinet/libalias/HISTORY
deleted file mode 100644
index 3d97fd0803b1..000000000000
--- a/sys/netinet/libalias/HISTORY
+++ /dev/null
@@ -1,129 +0,0 @@
-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.
-
-Verstion 1.7: January 9, 1997 (cjm)
- - Reduced malloc() activity for ICMP echo and
- timestamp requests.
-
- - Added handling for out-of-order IP fragments.
-
- - Switched to differential checksum computation
- for IP headers (TCP, UDP and ICMP checksums
- were already differential).
-
- - Accepts FTP data connections from other than
- port 20. This allows one ftp connections
- from two hosts which are both running packet
- aliasing.
-
- - Checksum error on FTP transfers. Problem
- in code located by Martin Renters and
- Brian Somers.
-
-Version 1.8: January 14, 1997 (cjm)
- - Fixed data type error in function StartPoint()
- in alias_db.c (this bug did not exist before v1.7)
- Problem in code located by Ari Suutari.
-
-Version 1.9: February 1, 1997 (Eivind Eklund <perhaps@yes.no>)
- - Added support for IRC DCC (ee)
-
- - Changed the aliasing routines to use ANSI style
- throughout (ee)
-
- - Minor API changes for integration with other
- programs than PPP (ee)
-
- - Fixed minor security hole in alias_ftp.c for
- other applications of the aliasing software.
- Hole could _not_ manifest in ppp+pktAlias, but
- could potentially manifest in other applications
- of the aliasing. (ee)
-
- - Connections initiated from packet aliasing
- host machine will not have their port number
- aliased unless it conflicts with an aliasing
- port already being used. (There is an option
- to disable this for debugging) (cjm)
-
- - Sockets will be allocated in cases where
- there might be port interference with the
- host machine. This can be disabled in cases
- where the ppp host will be acting purely as a
- masquerading router and not generate any
- traffic of its own.
- (cjm)
-
-Version 2.0: March, 1997 (cjm)
- - Aliasing links are cleared only when a host interface address
- changes.
-
- - PacketAliasPermanentLink() API added.
-
- - Option for only aliasing private, unregistered
- IP addresses added.
-
- - Substantial rework to the aliasing lookup engine.
-
-Version 2.1: May, 1997 (cjm)
- - Continuing rework to the aliasing lookup engine
- to support multiple incoming addresses and static
- NAT. PacketAliasRedirectPort() and
- PacketAliasRedirectAddr() added to API.
-
- - Now supports outgoing as well as incoming ICMP
- error messges.
-
-Version 2.2: July, 1997 (cjm)
- - Rationalized API function names to all begin with
- "PacketAlias..." Old function names are retained
- for backwards compatitibility.
-
- - 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.
diff --git a/sys/netinet/libalias/Makefile b/sys/netinet/libalias/Makefile
deleted file mode 100644
index 665d14e10b3d..000000000000
--- a/sys/netinet/libalias/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# $Id$
-
-LIB= alias
-SHLIB_MAJOR= 2
-SHLIB_MINOR= 5
-CFLAGS+= -Wall -I${.CURDIR}
-SRCS= alias.c alias_cuseeme.c alias_db.c alias_ftp.c alias_irc.c \
- alias_nbt.c alias_old.c alias_util.c
-MAN3= libalias.3
-
-beforeinstall:
- ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/alias.h \
- ${DESTDIR}/usr/include
-
-.include <bsd.lib.mk>
diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c
deleted file mode 100644
index 50e597f4364a..000000000000
--- a/sys/netinet/libalias/alias.c
+++ /dev/null
@@ -1,1165 +0,0 @@
-/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
-/*
- 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 do the same for IRC
- DCC. Alias_util.c contains a few utility routines.
-
- This software is placed into the public domain with no restrictions
- on its distribution.
-
- 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
-
- See HISTORY file for additional revisions.
-
-*/
-
-#include <stdio.h>
-#include <unistd.h>
-
-#include <sys/param.h>
-#include <sys/types.h>
-
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-
-#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 FTP_CONTROL_PORT_NUMBER 21
-#define IRC_CONTROL_PORT_NUMBER_1 6667
-#define IRC_CONTROL_PORT_NUMBER_2 6668
-#define CUSEEME_PORT_NUMBER 7648
-
-/*
- 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) { \
- 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; \
- } \
-}
-
-
-
-
-/* TCP Handling Routines
-
- TcpMonitorIn() -- These routines monitor TCP connections, and
- TcpMonitorOut() -- delete a link node when a connection is closed.
-
-These routines look for SYN, ACK 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 *link)
-{
- struct tcphdr *tc;
-
- tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
-
- switch (GetStateIn(link))
- {
- case ALIAS_TCP_STATE_NOT_CONNECTED:
- if (tc->th_flags & TH_SYN)
- SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
- break;
- case ALIAS_TCP_STATE_CONNECTED:
- if (tc->th_flags & TH_FIN
- || tc->th_flags & TH_RST)
- SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
- break;
- }
-}
-
-static void
-TcpMonitorOut(struct ip *pip, struct alias_link *link)
-{
- struct tcphdr *tc;
-
- tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
-
- switch (GetStateOut(link))
- {
- case ALIAS_TCP_STATE_NOT_CONNECTED:
- if (tc->th_flags & TH_SYN)
- SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
- break;
- case ALIAS_TCP_STATE_CONNECTED:
- if (tc->th_flags & TH_FIN
- || tc->th_flags & TH_RST)
- SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
- break;
- }
-}
-
-
-
-
-
-/* Protocol Specific Packet Aliasing Routines
-
- IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2(), IcmpAliasIn3()
- IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2(), IcmpAliasOut3()
- 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 is 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 ip *);
-static int IcmpAliasIn2(struct ip *);
-static int IcmpAliasIn3(struct ip *);
-static int IcmpAliasIn (struct ip *);
-
-static int IcmpAliasOut1(struct ip *);
-static int IcmpAliasOut2(struct ip *);
-static int IcmpAliasOut3(struct ip *);
-static int IcmpAliasOut (struct ip *);
-
-static int UdpAliasOut(struct ip *);
-static int UdpAliasIn (struct ip *);
-
-static int TcpAliasOut(struct ip *, int);
-static int TcpAliasIn (struct ip *);
-
-
-static int
-IcmpAliasIn1(struct ip *pip)
-{
-/*
- De-alias incoming echo and timestamp replies
-*/
- struct alias_link *link;
- struct icmp *ic;
-
- ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
-
-/* Get source address from ICMP data field and restore original data */
- link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id);
- if (link != NULL)
- {
- u_short original_id;
- int accumulate;
-
- original_id = GetOriginalPort(link);
-
-/* 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(link);
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &original_address,
- (u_short *) &pip->ip_dst,
- 2);
- pip->ip_dst = original_address;
- }
-
- return(PKT_ALIAS_OK);
- }
- return(PKT_ALIAS_IGNORED);
-}
-
-static int
-IcmpAliasIn2(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 *link;
-
- ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
- ip = (struct ip *) ic->icmp_data;
-
- ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
- tc = (struct tcphdr *) ud;
- ic2 = (struct icmp *) ud;
-
- if (ip->ip_p == IPPROTO_UDP)
- link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
- ud->uh_dport, ud->uh_sport,
- IPPROTO_UDP);
- else if (ip->ip_p == IPPROTO_TCP)
- link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
- tc->th_dport, tc->th_sport,
- IPPROTO_TCP);
- else if (ip->ip_p == IPPROTO_ICMP) {
- if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
- link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id);
- else
- link = NULL;
- } else
- link = NULL;
-
- if (link != NULL)
- {
- if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
- {
- u_short *sptr;
- int accumulate;
- struct in_addr original_address;
- u_short original_port;
-
- original_address = GetOriginalAddress(link);
- original_port = GetOriginalPort(link);
-
-/* Adjust ICMP checksum */
- sptr = (u_short *) &(ip->ip_src);
- accumulate = *sptr++;
- accumulate += *sptr;
- sptr = (u_short *) &original_address;
- accumulate -= *sptr++;
- accumulate -= *sptr;
- accumulate += ud->uh_sport;
- accumulate -= original_port;
- ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
-
-/* Un-alias address in IP header */
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &original_address,
- (u_short *) &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 (pip->ip_p == IPPROTO_ICMP)
- {
- u_short *sptr;
- int accumulate;
- struct in_addr original_address;
- u_short original_id;
-
- original_address = GetOriginalAddress(link);
- original_id = GetOriginalPort(link);
-
-/* Adjust ICMP checksum */
- sptr = (u_short *) &(ip->ip_src);
- accumulate = *sptr++;
- accumulate += *sptr;
- sptr = (u_short *) &original_address;
- accumulate -= *sptr++;
- accumulate -= *sptr;
- accumulate += ic2->icmp_id;
- accumulate -= original_id;
- ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
-
-/* Un-alias address in IP header */
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &original_address,
- (u_short *) &pip->ip_dst,
- 2);
- pip->ip_dst = original_address;
-
-/* Un-alias address of original IP packet and seqence 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
-IcmpAliasIn3(struct ip *pip)
-{
- struct in_addr original_address;
-
- original_address = FindOriginalAddress(pip->ip_dst);
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &original_address,
- (u_short *) &pip->ip_dst,
- 2);
- pip->ip_dst = original_address;
-
- return PKT_ALIAS_OK;
-}
-
-
-static int
-IcmpAliasIn(struct ip *pip)
-{
- int iresult;
- struct icmp *ic;
-
- ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
-
- iresult = PKT_ALIAS_IGNORED;
- switch (ic->icmp_type)
- {
- case ICMP_ECHOREPLY:
- case ICMP_TSTAMPREPLY:
- if (ic->icmp_code == 0)
- {
- iresult = IcmpAliasIn1(pip);
- }
- break;
- case ICMP_UNREACH:
- case ICMP_SOURCEQUENCH:
- case ICMP_TIMXCEED:
- case ICMP_PARAMPROB:
- iresult = IcmpAliasIn2(pip);
- break;
- case ICMP_ECHO:
- case ICMP_TSTAMP:
- iresult = IcmpAliasIn3(pip);
- break;
- }
- return(iresult);
-}
-
-
-static int
-IcmpAliasOut1(struct ip *pip)
-{
-/*
- Alias ICMP echo and timestamp packets
-*/
- struct alias_link *link;
- struct icmp *ic;
-
- ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
-
-/* Save overwritten data for when echo packet returns */
- link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id);
- if (link != NULL)
- {
- u_short alias_id;
- int accumulate;
-
- alias_id = GetAliasPort(link);
-
-/* 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(link);
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_address,
- (u_short *) &pip->ip_src,
- 2);
- pip->ip_src = alias_address;
- }
-
- return(PKT_ALIAS_OK);
- }
- return(PKT_ALIAS_IGNORED);
-}
-
-
-static int
-IcmpAliasOut2(struct ip *pip)
-{
-/*
- Alias outgoing ICMP error messages containing
- IP header and first 64 bits of datagram.
-*/
- struct in_addr alias_addr;
- struct ip *ip;
- struct icmp *ic;
-
- ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
- ip = (struct ip *) ic->icmp_data;
-
- alias_addr = FindAliasAddress(ip->ip_src);
-
-/* Alias destination address in IP fragment */
- DifferentialChecksum(&ic->icmp_cksum,
- (u_short *) &alias_addr,
- (u_short *) &ip->ip_dst,
- 2);
- ip->ip_dst = alias_addr;
-
-/* alias source address in IP header */
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_addr,
- (u_short *) &pip->ip_src,
- 2);
- pip->ip_src = alias_addr;
-
- return PKT_ALIAS_OK;
-}
-
-
-static int
-IcmpAliasOut3(struct ip *pip)
-{
-/*
- Handle outgoing echo and timestamp replies. The
- only thing which is done in this case is to alias
- the source IP address of the packet.
-*/
- struct in_addr alias_addr;
-
- alias_addr = FindAliasAddress(pip->ip_src);
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_addr,
- (u_short *) &pip->ip_src,
- 2);
- pip->ip_src = alias_addr;
-
- return PKT_ALIAS_OK;
-}
-
-
-static int
-IcmpAliasOut(struct ip *pip)
-{
- int iresult;
- struct icmp *ic;
-
- ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
-
- iresult = PKT_ALIAS_IGNORED;
- switch (ic->icmp_type)
- {
- case ICMP_ECHO:
- case ICMP_TSTAMP:
- if (ic->icmp_code == 0)
- {
- iresult = IcmpAliasOut1(pip);
- }
- break;
- case ICMP_UNREACH:
- case ICMP_SOURCEQUENCH:
- case ICMP_TIMXCEED:
- case ICMP_PARAMPROB:
- iresult = IcmpAliasOut2(pip);
- break;
- case ICMP_ECHOREPLY:
- case ICMP_TSTAMPREPLY:
- iresult = IcmpAliasOut3(pip);
- }
- return(iresult);
-}
-
-static int
-UdpAliasIn(struct ip *pip)
-{
- struct udphdr *ud;
- struct alias_link *link;
-
- ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
-
- link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
- ud->uh_sport, ud->uh_dport,
- IPPROTO_UDP);
- if (link != NULL)
- {
- struct in_addr alias_address;
- struct in_addr original_address;
- u_short alias_port;
- int accumulate;
- u_short *sptr;
- int r = 0;
-
- alias_address = GetAliasAddress(link);
- original_address = GetOriginalAddress(link);
- alias_port = ud->uh_dport;
- ud->uh_dport = GetOriginalPort(link);
-
-/* If NETBIOS Datagram, It should be alias address in UDP Data, too */
- if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
- || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
- {
- r = AliasHandleUdpNbt(pip, link, &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(pip, link,
- &alias_address,
- &alias_port,
- &original_address,
- &ud->uh_dport );
- }
-
- if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
- AliasHandleCUSeeMeIn(pip, original_address);
-
-/* If UDP checksum is not zero, then adjust since destination port */
-/* is being unaliased and destination port is being altered. */
- if (ud->uh_sum != 0)
- {
- accumulate = alias_port;
- accumulate -= ud->uh_dport;
- sptr = (u_short *) &alias_address;
- accumulate += *sptr++;
- accumulate += *sptr;
- sptr = (u_short *) &original_address;
- accumulate -= *sptr++;
- accumulate -= *sptr;
- ADJUST_CHECKSUM(accumulate, ud->uh_sum)
- }
-
-/* Restore original IP address */
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &original_address,
- (u_short *) &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 ip *pip)
-{
- struct udphdr *ud;
- struct alias_link *link;
-
- ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
-
- link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
- ud->uh_sport, ud->uh_dport,
- IPPROTO_UDP);
- if (link != NULL)
- {
- u_short alias_port;
- struct in_addr alias_address;
-
- alias_address = GetAliasAddress(link);
- alias_port = GetAliasPort(link);
-
- if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
- AliasHandleCUSeeMeOut(pip, link);
-
-/* If NETBIOS Datagram, It should be alias address in UDP Data, too */
- if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
- || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
- {
- AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
- } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
- || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER )
- {
- AliasHandleUdpNbtNS(pip, link,
- &pip->ip_src,
- &ud->uh_sport,
- &alias_address,
- &alias_port);
- }
-
-/* 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;
- u_short *sptr;
-
- accumulate = ud->uh_sport;
- accumulate -= alias_port;
- sptr = (u_short *) &(pip->ip_src);
- accumulate += *sptr++;
- accumulate += *sptr;
- sptr = (u_short *) &alias_address;
- accumulate -= *sptr++;
- accumulate -= *sptr;
- ADJUST_CHECKSUM(accumulate, ud->uh_sum)
- }
-
-/* Put alias port in UDP header */
- ud->uh_sport = alias_port;
-
-/* Change source address */
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_address,
- (u_short *) &pip->ip_src,
- 2);
- pip->ip_src = alias_address;
-
- return(PKT_ALIAS_OK);
- }
- return(PKT_ALIAS_IGNORED);
-}
-
-
-
-static int
-TcpAliasIn(struct ip *pip)
-{
- struct tcphdr *tc;
- struct alias_link *link;
-
- tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
-
- link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
- tc->th_sport, tc->th_dport,
- IPPROTO_TCP);
- if (link != NULL)
- {
- struct in_addr alias_address;
- struct in_addr original_address;
- u_short alias_port;
- int accumulate;
- u_short *sptr;
-
- alias_address = GetAliasAddress(link);
- original_address = GetOriginalAddress(link);
- alias_port = tc->th_dport;
- tc->th_dport = GetOriginalPort(link);
-
-/* Adjust TCP checksum since destination port is being unaliased */
-/* and destination port is being altered. */
- accumulate = alias_port;
- accumulate -= tc->th_dport;
- sptr = (u_short *) &alias_address;
- accumulate += *sptr++;
- accumulate += *sptr;
- sptr = (u_short *) &original_address;
- accumulate -= *sptr++;
- accumulate -= *sptr;
-
-/* See if ack number needs to be modified */
- if (GetAckModified(link) == 1)
- {
- int delta;
-
- delta = GetDeltaAckIn(pip, link);
- if (delta != 0)
- {
- sptr = (u_short *) &tc->th_ack;
- accumulate += *sptr++;
- accumulate += *sptr;
- tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
- sptr = (u_short *) &tc->th_ack;
- accumulate -= *sptr++;
- accumulate -= *sptr;
- }
- }
-
- ADJUST_CHECKSUM(accumulate, tc->th_sum);
-
-/* Restore original IP address */
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &original_address,
- (u_short *) &pip->ip_dst,
- 2);
- pip->ip_dst = original_address;
-
-/* Monitor TCP connection state */
- TcpMonitorIn(pip, link);
-
- return(PKT_ALIAS_OK);
- }
- return(PKT_ALIAS_IGNORED);
-}
-
-static int
-TcpAliasOut(struct ip *pip, int maxpacketsize)
-{
- struct tcphdr *tc;
- struct alias_link *link;
-
- tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
-
- link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
- tc->th_sport, tc->th_dport,
- IPPROTO_TCP);
- if (link !=NULL)
- {
- struct in_addr alias_address;
- u_short alias_port;
- int accumulate;
- u_short *sptr;
-
- alias_port = GetAliasPort(link);
- alias_address = GetAliasAddress(link);
-
-/* Monitor tcp connection state */
- TcpMonitorOut(pip, link);
-
-/* Special processing for ftp connection */
- if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
- || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
- AliasHandleFtpOut(pip, link, maxpacketsize);
- if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
- || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
- AliasHandleIrcOut(pip, link, maxpacketsize);
-
-/* Adjust TCP checksum since source port is being aliased */
-/* and source address is being altered */
- accumulate = tc->th_sport;
- accumulate -= alias_port;
- sptr = (u_short *) &(pip->ip_src);
- accumulate += *sptr++;
- accumulate += *sptr;
- sptr = (u_short *) &alias_address;
- accumulate -= *sptr++;
- accumulate -= *sptr;
-
-/* Modify sequence number if necessary */
- if (GetAckModified(link) == 1)
- {
- int delta;
-
- delta = GetDeltaSeqOut(pip, link);
- if (delta != 0)
- {
- sptr = (u_short *) &tc->th_seq;
- accumulate += *sptr++;
- accumulate += *sptr;
- tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
- sptr = (u_short *) &tc->th_seq;
- accumulate -= *sptr++;
- accumulate -= *sptr;
- }
- }
-
- ADJUST_CHECKSUM(accumulate, tc->th_sum)
-
-/* Put alias address in TCP header */
- tc->th_sport = alias_port;
-
-/* Change source address */
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_address,
- (u_short *) &pip->ip_src,
- 2);
- pip->ip_src = alias_address;
-
- 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 ip *);
-static int FragmentOut(struct ip *);
-
-
-static int
-FragmentIn(struct ip *pip)
-{
- struct alias_link *link;
-
- link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
- if (link != NULL)
- {
- struct in_addr original_address;
-
- GetFragmentAddr(link, &original_address);
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &original_address,
- (u_short *) &pip->ip_dst,
- 2);
- pip->ip_dst = original_address;
-
- return(PKT_ALIAS_OK);
- }
- return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
-}
-
-
-static int
-FragmentOut(struct ip *pip)
-{
- struct in_addr alias_address;
-
- alias_address = FindAliasAddress(pip->ip_src);
- DifferentialChecksum(&pip->ip_sum,
- (u_short *) &alias_address,
- (u_short *) &pip->ip_src,
- 2);
- pip->ip_src = alias_address;
-
- return(PKT_ALIAS_OK);
-}
-
-
-
-
-
-
-/* Outside World Access
-
- PacketAliasSaveFragment()
- PacketAliasGetFragment()
- PacketAliasFragmentIn()
- PacketAliasIn()
- PacketAliasOut()
-
-(prototypes in alias.h)
-*/
-
-
-int
-PacketAliasSaveFragment(char *ptr)
-{
- int iresult;
- struct alias_link *link;
- struct ip *pip;
-
- pip = (struct ip *) ptr;
- link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
- iresult = PKT_ALIAS_ERROR;
- if (link != NULL)
- {
- SetFragmentPtr(link, ptr);
- iresult = PKT_ALIAS_OK;
- }
- return(iresult);
-}
-
-
-char *
-PacketAliasGetFragment(char *ptr)
-{
- struct alias_link *link;
- char *fptr;
- struct ip *pip;
-
- pip = (struct ip *) ptr;
- link = FindFragmentPtr(pip->ip_src, pip->ip_id);
- if (link != NULL)
- {
- GetFragmentPtr(link, &fptr);
- SetFragmentPtr(link, NULL);
- SetExpire(link, 0); /* Deletes link */
-
- return(fptr);
- }
- else
- {
- return(NULL);
- }
-}
-
-
-void
-PacketAliasFragmentIn(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;
-
- pip = (struct ip *) ptr;
- fpip = (struct ip *) ptr_fragment;
-
- DifferentialChecksum(&fpip->ip_sum,
- (u_short *) &pip->ip_dst,
- (u_short *) &fpip->ip_dst,
- 2);
- fpip->ip_dst = pip->ip_dst;
-}
-
-
-int
-PacketAliasIn(char *ptr, int maxpacketsize)
-{
- struct in_addr alias_addr;
- struct ip *pip;
- int iresult;
-
- HouseKeeping();
- ClearCheckNewLink();
- 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(pip);
- break;
- case IPPROTO_UDP:
- iresult = UdpAliasIn(pip);
- break;
- case IPPROTO_TCP:
- iresult = TcpAliasIn(pip);
- break;
- }
-
- if (ntohs(pip->ip_off) & IP_MF)
- {
- struct alias_link *link;
-
- link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
- if (link != NULL)
- {
- iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
- SetFragmentAddr(link, pip->ip_dst);
- }
- else
- {
- iresult = PKT_ALIAS_ERROR;
- }
- }
- }
- else
- {
- iresult = FragmentIn(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
-PacketAliasOut(char *ptr, /* valid IP packet */
- int maxpacketsize /* How much the packet data may grow
- (FTP and IRC inline changes) */
- )
-{
- int iresult;
- struct in_addr addr_save;
- struct ip *pip;
-
- HouseKeeping();
- ClearCheckNewLink();
- 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();
- if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
- {
- unsigned int 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(pip->ip_src);
- }
- }
-
- iresult = PKT_ALIAS_IGNORED;
- if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
- {
- switch (pip->ip_p)
- {
- case IPPROTO_ICMP:
- iresult = IcmpAliasOut(pip);
- break;
- case IPPROTO_UDP:
- iresult = UdpAliasOut(pip);
- break;
- case IPPROTO_TCP:
- iresult = TcpAliasOut(pip, maxpacketsize);
- break;
- }
- }
- else
- {
- iresult = FragmentOut(pip);
- }
-
- SetDefaultAliasAddress(addr_save);
- return(iresult);
-}
diff --git a/sys/netinet/libalias/alias.h b/sys/netinet/libalias/alias.h
deleted file mode 100644
index 010db9885a5a..000000000000
--- a/sys/netinet/libalias/alias.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*lint -save -library Flexelint comment for external headers */
-
-/*
- 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.
-
- $Id: alias.h,v 1.7 1998/01/16 12:56:07 bde Exp $
-*/
-
-
-#ifndef _ALIAS_H_
-#define _ALIAS_H_
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/* Alias link representative (incomplete struct) */
-struct alias_link;
-
-/* External interfaces (API) to packet aliasing engine */
-
-/* Initialization and Control */
- extern void
- PacketAliasInit(void);
-
- extern void
- PacketAliasUninit(void);
-
- extern void
- PacketAliasSetAddress(struct in_addr);
-
- extern unsigned int
- PacketAliasSetMode(unsigned int, unsigned int);
-
-#ifndef NO_FW_PUNCH
- extern void
- PacketAliasSetFWBase(unsigned int, unsigned int);
-#endif
-
-/* Packet Handling */
- extern int
- PacketAliasIn(char *, int maxpacketsize);
-
- extern int
- PacketAliasOut(char *, int maxpacketsize);
-
-/* Port and Address Redirection */
- extern struct alias_link *
- PacketAliasRedirectPort(struct in_addr, u_short,
- struct in_addr, u_short,
- struct in_addr, u_short,
- u_char);
-
- extern struct alias_link *
- PacketAliasRedirectAddr(struct in_addr,
- struct in_addr);
-
- extern void
- PacketAliasRedirectDelete(struct alias_link *);
-
-/* Fragment Handling */
- extern int
- PacketAliasSaveFragment(char *);
-
- extern char *
- PacketAliasGetFragment(char *);
-
- extern void
- PacketAliasFragmentIn(char *, char *);
-
-/* Miscellaneous Functions */
- extern void
- PacketAliasSetTarget(struct in_addr addr);
-
- extern int
- PacketAliasCheckNewLink(void);
-
- extern u_short
- PacketAliasInternetChecksum(u_short *, int);
-
-
-/*
- In version 2.2, the function names were rationalized
- to all be of the form PacketAlias... These are the
- old function names for backwards compatibility
-*/
-extern int SaveFragmentPtr(char *);
-extern char *GetNextFragmentPtr(char *);
-extern void FragmentAliasIn(char *, char *);
-extern void SetPacketAliasAddress(struct in_addr);
-extern void InitPacketAlias(void);
-extern unsigned int SetPacketAliasMode(unsigned int, unsigned int);
-extern int PacketAliasIn2(char *, struct in_addr, int maxpacketsize);
-extern int PacketAliasOut2(char *, struct in_addr, int maxpacketsize);
-extern int
-PacketAliasPermanentLink(struct in_addr, u_short,
- struct in_addr, u_short,
- u_short, u_char);
-extern u_short InternetChecksum(u_short *, int);
-
-/* Obsolete constant */
-#define PKT_ALIAS_NEW_LINK 5
-
-/********************** Mode flags ********************/
-/* Set these flags using SetPacketAliasMode() */
-
-/* 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 eg 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 with
- unregistered source addresses will be aliased (along with those
- of the ppp host maching itself. 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 functions 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. Where (IPFW "line-numbers") the hole is created is
- controlled by PacketAliasSetFWBase(base, size). The hole will be
- attached to that particular alias_link, so when the link goes away
- so do the hole. */
-#define PKT_ALIAS_PUNCH_FW 0x40
-#endif
-
-/* 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
-/*lint -restore */
diff --git a/sys/netinet/libalias/alias_cuseeme.c b/sys/netinet/libalias/alias_cuseeme.c
deleted file mode 100644
index 7cb6d4ea4ee4..000000000000
--- a/sys/netinet/libalias/alias_cuseeme.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*-
- * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
- * with the aid of code written by
- * Junichi SATOH <junichi@astec.co.jp> 1996, 1997.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id$
- */
-
-#include <sys/types.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-
-#include "alias_local.h"
-
-/* CU-SeeMe Data Header */
-struct cu_header {
- u_int16_t dest_family;
- u_int16_t dest_port;
- u_int32_t dest_addr;
- int16_t family;
- u_int16_t port;
- u_int32_t addr;
- u_int32_t seq;
- u_int16_t msg;
- u_int16_t data_type;
- u_int16_t packet_len;
-};
-
-/* Open Continue Header */
-struct oc_header {
- u_int16_t client_count; /* Number of client info structs */
- u_int32_t seq_no;
- char user_name[20];
- char reserved[4]; /* flags, version stuff, etc */
-};
-
-/* client info structures */
-struct client_info {
- u_int32_t address; /* Client address */
- char reserved[8]; /* Flags, pruning bitfield, packet counts etc */
-};
-
-void
-AliasHandleCUSeeMeOut(struct ip *pip, struct alias_link *link)
-{
- struct udphdr *ud;
-
- ud = (struct udphdr *)((char *)pip + (pip->ip_hl << 2));
- if(ud->uh_ulen >= sizeof(struct cu_header)) {
- struct cu_header *cu;
- struct alias_link *cu_link;
-
- cu = (struct cu_header *)(ud + 1);
- if (cu->addr)
- cu->addr = (u_int32_t)GetAliasAddress(link).s_addr;
-
- cu_link = FindUdpTcpOut(pip->ip_src, GetDestAddress(link),
- ud->uh_dport, 0, IPPROTO_UDP);
-
-#ifndef NO_FW_PUNCH
- if (cu_link)
- PunchFWHole(cu_link);
-#endif
- }
-}
-
-void
-AliasHandleCUSeeMeIn(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;
-
- alias_addr.s_addr = pip->ip_dst.s_addr;
- ud = (struct udphdr *)((char *)pip + (pip->ip_hl << 2));
- cu = (struct cu_header *)(ud + 1);
- oc = (struct oc_header *)(cu + 1);
- ci = (struct client_info *)(oc + 1);
- end = (char *)cu + 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/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c
deleted file mode 100644
index dc9d020bd858..000000000000
--- a/sys/netinet/libalias/alias_db.c
+++ /dev/null
@@ -1,2241 +0,0 @@
-/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*-
- 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.
-
-
- This software is placed into the public domain with no restrictions
- on its distribution.
-
- 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 unspecied 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 now are available through
- a new interface, SetPacketAliasMode(). This allow 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 permament 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.
-
- See HISTORY file for additional revisions.
-*/
-
-
-/* System include files */
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <sys/errno.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-/* BSD network include files */
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-
-#include "alias.h"
-#include "alias_local.h"
-
-
-
-/*
- Constants (note: constants are also defined
- near relevant functions or structs)
-*/
-
-/* Sizes of input and output link tables */
-#define LINK_TABLE_OUT_SIZE 101
-#define LINK_TABLE_IN_SIZE 4001
-
-/* Parameters used for cleanup of expired links */
-#define ALIAS_CLEANUP_INTERVAL_SECS 60
-#define ALIAS_CLEANUP_MAX_SPOKES 30
-
-/* Timouts (in seconds) for different link types) */
-#define ICMP_EXPIRE_TIME 60
-#define UDP_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 numbea. */
-
-#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
- framgents 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 addreess, destination address, source port, destination
- port and link type.
-*/
-
-struct ack_data_record /* used to save changes to ack/seq 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 seq 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 alias_link /* Main data structure */
-{
- struct in_addr src_addr; /* Address and port information */
- struct in_addr dst_addr; /* . */
- struct in_addr alias_addr; /* . */
- u_short src_port; /* . */
- u_short dst_port; /* . */
- u_short alias_port; /* . */
-
- int link_type; /* Type of link: tcp, udp, icmp, frag */
-
-/* values for link_type */
-#define LINK_ICMP 1
-#define LINK_UDP 2
-#define LINK_TCP 3
-#define LINK_FRAGMENT_ID 4
-#define LINK_FRAGMENT_PTR 5
-#define LINK_ADDR 6
-
- int flags; /* indicates special characteristics */
-
-/* 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 */
-
- u_int start_point_out; /* Index number in output lookup table */
- u_int start_point_in;
- struct alias_link *next_out; /* Linked list pointers for input and */
- struct alias_link *last_out; /* output tables */
- struct alias_link *next_in; /* . */
- struct alias_link *last_in; /* . */
-
- union /* Auxiliary data */
- {
- char *frag_ptr;
- struct in_addr frag_addr;
- struct tcp_dat *tcp;
- } data;
-};
-
-
-
-
-
-/* Global Variables
-
- The global variables listed here are only accessed from
- within alias_db.c and so are prefixed with the static
- designation.
-*/
-
-int packetAliasMode; /* Mode flags */
- /* - documented in alias.h */
-
-static struct in_addr aliasAddress; /* Address written onto source */
- /* field of IP packet. */
-
-static struct in_addr targetAddress; /* IP address incoming packets */
- /* are sent to if no aliasing */
- /* link already exists */
-
-static struct in_addr nullAddress; /* Used as a dummy parameter for */
- /* some function calls */
-static struct alias_link *
-linkTableOut[LINK_TABLE_OUT_SIZE]; /* Lookup table of pointers to */
- /* chains of link records. Each */
-static struct alias_link * /* link record is doubly indexed */
-linkTableIn[LINK_TABLE_IN_SIZE]; /* into input and output lookup */
- /* tables. */
-
-static int icmpLinkCount; /* Link statistics */
-static int udpLinkCount;
-static int tcpLinkCount;
-static int fragmentIdLinkCount;
-static int fragmentPtrLinkCount;
-static int sockCount;
-
-static int cleanupIndex; /* Index to chain of link table */
- /* being inspected for old links */
-
-static int timeStamp; /* System time in seconds for */
- /* current packet */
-
-static int lastCleanupTime; /* Last time IncrementalCleanup() */
- /* was called */
-
-static int houseKeepingResidual; /* used by HouseKeeping() */
-
-static int deleteAllLinks; /* If equal to zero, DeleteLink() */
- /* will not remove permanent links */
-
-static FILE *monitorFile; /* File descriptor for link */
- /* statistics monitoring file */
-
-static int newDefaultLink; /* Indicates if a new aliasing */
- /* link has been created after a */
- /* call to PacketAliasIn/Out(). */
-
-#ifndef NO_FW_PUNCH
-static int fireWallFD = -1; /* File descriptor to be able to */
- /* control firewall. Opened by */
- /* PacketAliasSetMode on first */
- /* setting the PKT_ALIAS_PUNCH_FW */
- /* flag. */
-#endif
-
-
-
-
-
-
-/* Internal utility routines (used only in alias_db.c)
-
-Lookup table starting points:
- StartPointIn() -- link table initial search point for
- outgoing packets
- StartPointOut() -- port table initial search point for
- incoming 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(void);
-
-#ifndef NO_FW_PUNCH
-/* Firewall control */
-static void InitPunchFW(void);
-static void UninitPunchFW(void);
-static void ClearFWHole(struct alias_link *link);
-#endif
-
-/* Log file control */
-static void InitPacketAliasLog(void);
-static void UninitPacketAliasLog(void);
-
-static u_int
-StartPointIn(struct in_addr alias_addr,
- u_short alias_port,
- int link_type)
-{
- u_int n;
-
- n = alias_addr.s_addr;
- 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;
- 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(void)
-{
-/* Used for debugging */
-
- if (monitorFile)
- {
- fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, frag_id=%d frag_ptr=%d",
- icmpLinkCount,
- udpLinkCount,
- tcpLinkCount,
- fragmentIdLinkCount,
- fragmentPtrLinkCount);
-
- fprintf(monitorFile, " / tot=%d (sock=%d)\n",
- icmpLinkCount + udpLinkCount
- + tcpLinkCount
- + fragmentIdLinkCount
- + fragmentPtrLinkCount,
- sockCount);
-
- fflush(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
-*/
-
-/* Local prototypes */
-static int GetNewPort(struct alias_link *, int);
-
-static u_short GetSocket(u_short, int *, int);
-
-static void CleanupAliasData(void);
-
-static void IncrementalCleanup(void);
-
-static void DeleteLink(struct alias_link *);
-
-static struct alias_link *
-AddLink(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 in_addr, struct in_addr, u_short, u_short, int);
-
-static struct alias_link *
-FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int);
-
-
-#define ALIAS_PORT_BASE 0x08000
-#define ALIAS_PORT_MASK 0x07fff
-#define GET_NEW_PORT_MAX_ATTEMPTS 20
-
-#define GET_ALIAS_PORT -1
-#define GET_ALIAS_ID GET_ALIAS_PORT
-
-/* 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 alias_link *link, 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.
-
- Whis this parameter is -1, 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 (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_net = link->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)
- {
- link->alias_port = (u_short) alias_port_param;
- return(0);
- }
- else
- {
- fprintf(stderr, "PacketAlias/GetNewPort(): ");
- fprintf(stderr, "input parameter error\n");
- return(-1);
- }
-
-
-/* Port number search */
- for (i=0; i<max_trials; i++)
- {
- int go_ahead;
- struct alias_link *search_result;
-
- search_result = FindLinkIn(link->dst_addr, link->alias_addr,
- link->dst_port, port_net,
- link->link_type, 0);
-
- if (search_result == NULL)
- go_ahead = 1;
- else if (!(link->flags & LINK_PARTIALLY_SPECIFIED)
- && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
- go_ahead = 1;
- else
- go_ahead = 0;
-
- if (go_ahead)
- {
- if ((packetAliasMode && PKT_ALIAS_USE_SOCKETS)
- && (link->flags & LINK_PARTIALLY_SPECIFIED))
- {
- if (GetSocket(port_net, &link->sockfd, link->link_type))
- {
- link->alias_port = port_net;
- return(0);
- }
- }
- else
- {
- link->alias_port = port_net;
- return(0);
- }
- }
-
- port_sys = random() & ALIAS_PORT_MASK;
- port_sys += ALIAS_PORT_BASE;
- port_net = htons(port_sys);
- }
-
- fprintf(stderr, "PacketAlias/GetnewPort(): ");
- fprintf(stderr, "could not find free port\n");
-
- return(-1);
-}
-
-
-static u_short
-GetSocket(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
- {
- fprintf(stderr, "PacketAlias/GetSocket(): ");
- fprintf(stderr, "incorrect link type\n");
- return(0);
- }
-
- if (sock < 0)
- {
- fprintf(stderr, "PacketAlias/GetSocket(): ");
- fprintf(stderr, "socket() error %d\n", *sockfd);
- 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)
- {
- sockCount++;
- *sockfd = sock;
- return(1);
- }
- else
- {
- close(sock);
- return(0);
- }
-}
-
-
-static void
-CleanupAliasData(void)
-{
- struct alias_link *link;
- int i, icount;
-
- icount = 0;
- for (i=0; i<LINK_TABLE_OUT_SIZE; i++)
- {
- link = linkTableOut[i];
- while (link != NULL)
- {
- struct alias_link *link_next;
- link_next = link->next_out;
- icount++;
- DeleteLink(link);
- link = link_next;
- }
- }
-
- cleanupIndex =0;
-}
-
-
-static void
-IncrementalCleanup(void)
-{
- int icount;
- struct alias_link *link;
-
- icount = 0;
- link = linkTableOut[cleanupIndex++];
- while (link != NULL)
- {
- int idelta;
- struct alias_link *link_next;
-
- link_next = link->next_out;
- idelta = timeStamp - link->timestamp;
- switch (link->link_type)
- {
- case LINK_ICMP:
- case LINK_UDP:
- case LINK_FRAGMENT_ID:
- case LINK_FRAGMENT_PTR:
- if (idelta > link->expire_time)
- {
- DeleteLink(link);
- icount++;
- }
- break;
- case LINK_TCP:
- if (idelta > link->expire_time)
- {
- struct tcp_dat *tcp_aux;
-
- tcp_aux = link->data.tcp;
- if (tcp_aux->state.in != ALIAS_TCP_STATE_CONNECTED
- || tcp_aux->state.out != ALIAS_TCP_STATE_CONNECTED)
- {
- DeleteLink(link);
- icount++;
- }
- }
- break;
- }
- link = link_next;
- }
-
- if (cleanupIndex == LINK_TABLE_OUT_SIZE)
- cleanupIndex = 0;
-}
-
-void
-DeleteLink(struct alias_link *link)
-{
- struct alias_link *link_last;
- struct alias_link *link_next;
-
-/* Don't do anything if the link is marked permanent */
- if (deleteAllLinks == 0 && link->flags & LINK_PERMANENT)
- return;
-
-#ifndef NO_FW_PUNCH
-/* Delete associatied firewall hole, if any */
- ClearFWHole(link);
-#endif
-
-/* Adjust output table pointers */
- link_last = link->last_out;
- link_next = link->next_out;
-
- if (link_last != NULL)
- link_last->next_out = link_next;
- else
- linkTableOut[link->start_point_out] = link_next;
-
- if (link_next != NULL)
- link_next->last_out = link_last;
-
-/* Adjust input table pointers */
- link_last = link->last_in;
- link_next = link->next_in;
-
- if (link_last != NULL)
- link_last->next_in = link_next;
- else
- linkTableIn[link->start_point_in] = link_next;
-
- if (link_next != NULL)
- link_next->last_in = link_last;
-
-/* Close socket, if one has been allocated */
- if (link->sockfd != -1)
- {
- sockCount--;
- close(link->sockfd);
- }
-
-/* Link-type dependent cleanup */
- switch(link->link_type)
- {
- case LINK_ICMP:
- icmpLinkCount--;
- break;
- case LINK_UDP:
- udpLinkCount--;
- break;
- case LINK_TCP:
- tcpLinkCount--;
- if (link->data.tcp != NULL)
- free(link->data.tcp);
- break;
- case LINK_FRAGMENT_ID:
- fragmentIdLinkCount--;
- break;
- case LINK_FRAGMENT_PTR:
- fragmentPtrLinkCount--;
- if (link->data.frag_ptr != NULL)
- free(link->data.frag_ptr);
- break;
- }
-
-/* Free memory */
- free(link);
-
-/* Write statistics, if logging enabled */
- if (packetAliasMode & PKT_ALIAS_LOG)
- {
- ShowAliasStats();
- }
-}
-
-
-static struct alias_link *
-AddLink(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 *link;
- struct alias_link *first_link;
-
- link = malloc(sizeof(struct alias_link));
- if (link != NULL)
- {
- /* If either the aliasing address or source address are
- equal to the default device address (equal to the
- global variable aliasAddress), then set the alias
- address field of the link record to zero */
-
- if (src_addr.s_addr == aliasAddress.s_addr)
- src_addr.s_addr = 0;
-
- if (alias_addr.s_addr == aliasAddress.s_addr)
- alias_addr.s_addr = 0;
-
- /* Basic initialization */
- link->src_addr = src_addr;
- link->dst_addr = dst_addr;
- link->src_port = src_port;
- link->alias_addr = alias_addr;
- link->dst_port = dst_port;
- link->link_type = link_type;
- link->sockfd = -1;
- link->flags = 0;
- link->timestamp = timeStamp;
-
- /* Expiration time */
- switch (link_type)
- {
- case LINK_ICMP:
- link->expire_time = ICMP_EXPIRE_TIME;
- break;
- case LINK_UDP:
- link->expire_time = UDP_EXPIRE_TIME;
- break;
- case LINK_TCP:
- link->expire_time = TCP_EXPIRE_INITIAL;
- break;
- case LINK_FRAGMENT_ID:
- link->expire_time = FRAGMENT_ID_EXPIRE_TIME;
- break;
- case LINK_FRAGMENT_PTR:
- link->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
- break;
- }
-
- /* Determine alias flags */
- if (dst_addr.s_addr == 0)
- link->flags |= LINK_UNKNOWN_DEST_ADDR;
- if (dst_port == 0)
- link->flags |= LINK_UNKNOWN_DEST_PORT;
-
- /* Determine alias port */
- if (GetNewPort(link, alias_port_param) != 0)
- {
- free(link);
- return(NULL);
- }
-
- /* Set up pointers for output lookup table */
- start_point = StartPointOut(src_addr, dst_addr,
- src_port, dst_port, link_type);
- first_link = linkTableOut[start_point];
-
- link->last_out = NULL;
- link->next_out = first_link;
- link->start_point_out = start_point;
-
- if (first_link != NULL)
- first_link->last_out = link;
-
- linkTableOut[start_point] = link;
-
- /* Set up pointers for input lookup table */
- start_point = StartPointIn(alias_addr, link->alias_port, link_type);
- first_link = linkTableIn[start_point];
-
- link->last_in = NULL;
- link->next_in = first_link;
- link->start_point_in = start_point;
-
- if (first_link != NULL)
- first_link->last_in = link;
-
- linkTableIn[start_point] = link;
-
- /* Link-type dependent initialization */
- switch(link_type)
- {
- struct tcp_dat *aux_tcp;
-
- case LINK_ICMP:
- icmpLinkCount++;
- break;
- case LINK_UDP:
- udpLinkCount++;
- break;
- case LINK_TCP:
- aux_tcp = malloc(sizeof(struct tcp_dat));
- link->data.tcp = aux_tcp;
- if (aux_tcp != NULL)
- {
- int i;
-
- 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;
- }
- else
- {
- fprintf(stderr, "PacketAlias/AddLink: ");
- fprintf(stderr, " cannot allocate auxiliary TCP data\n");
- }
- break;
- case LINK_FRAGMENT_ID:
- fragmentIdLinkCount++;
- break;
- case LINK_FRAGMENT_PTR:
- fragmentPtrLinkCount++;
- break;
- }
- }
- else
- {
- fprintf(stderr, "PacketAlias/AddLink(): ");
- fprintf(stderr, "malloc() call failed.\n");
- }
-
- if (packetAliasMode & PKT_ALIAS_LOG)
- {
- ShowAliasStats();
- }
-
- return(link);
-}
-
-static struct alias_link *
-ReLink(struct alias_link *old_link,
- 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_link; /* zero, equal to alias port */
-
- new_link = AddLink(src_addr, dst_addr, alias_addr,
- src_port, dst_port, alias_port_param,
- link_type);
-#ifndef NO_FW_PUNCH
- if (new_link != NULL &&
- old_link->link_type == LINK_TCP &&
- old_link->data.tcp &&
- old_link->data.tcp->fwhole > 0) {
- PunchFWHole(new_link);
- }
-#endif
- DeleteLink(old_link);
- return new_link;
-}
-
-static struct alias_link *
-FindLinkOut(struct in_addr src_addr,
- struct in_addr dst_addr,
- u_short src_port,
- u_short dst_port,
- int link_type)
-{
- u_int i;
- struct alias_link *link;
-
- if (src_addr.s_addr == aliasAddress.s_addr)
- src_addr.s_addr = 0;
-
- i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
- link = linkTableOut[i];
- while (link != NULL)
- {
- if (link->src_addr.s_addr == src_addr.s_addr
- && link->dst_addr.s_addr == dst_addr.s_addr
- && link->dst_port == dst_port
- && link->src_port == src_port
- && link->link_type == link_type)
- {
- link->timestamp = timeStamp;
- break;
- }
- link = link->next_out;
- }
-
- return(link);
-}
-
-
-struct alias_link *
-FindLinkIn(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 *link;
- struct alias_link *link_fully_specified;
- struct alias_link *link_unknown_all;
- struct alias_link *link_unknown_dst_addr;
- struct alias_link *link_unknown_dst_port;
-
-/* Initialize pointers */
- link_fully_specified = NULL;
- link_unknown_all = NULL;
- link_unknown_dst_addr = NULL;
- link_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 == 0)
- flags_in |= LINK_UNKNOWN_DEST_ADDR;
- if (dst_port == 0)
- flags_in |= LINK_UNKNOWN_DEST_PORT;
-
-/* The following allows permanent links to be
- be specified as using the default aliasing address
- (i.e. device interface address) without knowing
- in advance what that address is. */
-
- if (alias_addr.s_addr == aliasAddress.s_addr)
- alias_addr.s_addr = 0;
-
-/* Search loop */
- start_point = StartPointIn(alias_addr, alias_port, link_type);
- link = linkTableIn[start_point];
- while (link != NULL)
- {
- int flags;
-
- flags = flags_in | link->flags;
- if (!(flags & LINK_PARTIALLY_SPECIFIED))
- {
- if (link->alias_addr.s_addr == alias_addr.s_addr
- && link->alias_port == alias_port
- && link->dst_addr.s_addr == dst_addr.s_addr
- && link->dst_port == dst_port
- && link->link_type == link_type)
- {
- link_fully_specified = link;
- break;
- }
- }
- else if ((flags & LINK_UNKNOWN_DEST_ADDR)
- && (flags & LINK_UNKNOWN_DEST_PORT))
- {
- if (link->alias_addr.s_addr == alias_addr.s_addr
- && link->alias_port == alias_port
- && link->link_type == link_type)
- {
- if (link_unknown_all == NULL)
- link_unknown_all = link;
- }
- }
- else if (flags & LINK_UNKNOWN_DEST_ADDR)
- {
- if (link->alias_addr.s_addr == alias_addr.s_addr
- && link->alias_port == alias_port
- && link->link_type == link_type
- && link->dst_port == dst_port)
- {
- if (link_unknown_dst_addr == NULL)
- link_unknown_dst_addr = link;
- }
- }
- else if (flags & LINK_UNKNOWN_DEST_PORT)
- {
- if (link->alias_addr.s_addr == alias_addr.s_addr
- && link->alias_port == alias_port
- && link->link_type == link_type
- && link->dst_addr.s_addr == dst_addr.s_addr)
- {
- if (link_unknown_dst_port == NULL)
- link_unknown_dst_port = link;
- }
- }
- link = link->next_in;
- }
-
-
-
- if (link_fully_specified != NULL)
- {
- return link_fully_specified;
- }
- else if (link_unknown_dst_port != NULL)
- {
- return replace_partial_links
- ? ReLink(link_unknown_dst_port,
- link_unknown_dst_port->src_addr, dst_addr, alias_addr,
- link_unknown_dst_port->src_port, dst_port, alias_port,
- link_type)
- : link_unknown_dst_port;
- }
- else if (link_unknown_dst_addr != NULL)
- {
- return replace_partial_links
- ? ReLink(link_unknown_dst_addr,
- link_unknown_dst_addr->src_addr, dst_addr, alias_addr,
- link_unknown_dst_addr->src_port, dst_port, alias_port,
- link_type)
- : link_unknown_dst_addr;
- }
- else if (link_unknown_all != NULL)
- {
- return replace_partial_links
- ? ReLink(link_unknown_all,
- link_unknown_all->src_addr, dst_addr, alias_addr,
- link_unknown_all->src_port, dst_port, alias_port,
- link_type)
- : link_unknown_all;
- }
- else
- {
- return(NULL);
- }
-}
-
-
-
-
-/* External routines for finding/adding links
-
--- "external" means outside alias_db.c, but within alias*.c --
-
- FindIcmpIn(), FindIcmpOut()
- FindFragmentIn1(), FindFragmentIn2()
- AddFragmentPtrLink(), FindFragmentPtr()
- FindUdpTcpIn(), FindUdpTcpOut()
- FindOriginalAddress(), FindAliasAddress()
-
-(prototypes in alias_local.h)
-*/
-
-
-struct alias_link *
-FindIcmpIn(struct in_addr dst_addr,
- struct in_addr alias_addr,
- u_short id_alias)
-{
- return FindLinkIn(dst_addr, alias_addr,
- NO_DEST_PORT, id_alias,
- LINK_ICMP, 0);
-}
-
-
-struct alias_link *
-FindIcmpOut(struct in_addr src_addr,
- struct in_addr dst_addr,
- u_short id)
-{
- struct alias_link * link;
-
- link = FindLinkOut(src_addr, dst_addr,
- id, NO_DEST_PORT,
- LINK_ICMP);
- if (link == NULL)
- {
- struct in_addr alias_addr;
-
- alias_addr = FindAliasAddress(src_addr);
- link = AddLink(src_addr, dst_addr, alias_addr,
- id, NO_DEST_PORT, GET_ALIAS_ID,
- LINK_ICMP);
- }
-
- return(link);
-}
-
-
-struct alias_link *
-FindFragmentIn1(struct in_addr dst_addr,
- struct in_addr alias_addr,
- u_short ip_id)
-{
- struct alias_link *link;
-
- link = FindLinkIn(dst_addr, alias_addr,
- NO_DEST_PORT, ip_id,
- LINK_FRAGMENT_ID, 0);
-
- if (link == NULL)
- {
- link = AddLink(nullAddress, dst_addr, alias_addr,
- NO_SRC_PORT, NO_DEST_PORT, ip_id,
- LINK_FRAGMENT_ID);
- }
-
- return(link);
-}
-
-
-struct alias_link *
-FindFragmentIn2(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(dst_addr, alias_addr,
- NO_DEST_PORT, ip_id,
- LINK_FRAGMENT_ID, 0);
-}
-
-
-struct alias_link *
-AddFragmentPtrLink(struct in_addr dst_addr,
- u_short ip_id)
-{
- return AddLink(nullAddress, dst_addr, nullAddress,
- NO_SRC_PORT, NO_DEST_PORT, ip_id,
- LINK_FRAGMENT_PTR);
-}
-
-
-struct alias_link *
-FindFragmentPtr(struct in_addr dst_addr,
- u_short ip_id)
-{
- return FindLinkIn(dst_addr, nullAddress,
- NO_DEST_PORT, ip_id,
- LINK_FRAGMENT_PTR, 0);
-}
-
-
-struct alias_link *
-FindUdpTcpIn(struct in_addr dst_addr,
- struct in_addr alias_addr,
- u_short dst_port,
- u_short alias_port,
- u_char proto)
-{
- int link_type;
- struct alias_link *link;
-
- switch (proto)
- {
- case IPPROTO_UDP:
- link_type = LINK_UDP;
- break;
- case IPPROTO_TCP:
- link_type = LINK_TCP;
- break;
- default:
- return NULL;
- break;
- }
-
- link = FindLinkIn(dst_addr, alias_addr,
- dst_port, alias_port,
- link_type, 1);
-
- if ( !(packetAliasMode & PKT_ALIAS_DENY_INCOMING) && link == NULL)
- {
- struct in_addr target_addr;
-
- target_addr = FindOriginalAddress(alias_addr);
- link = AddLink(target_addr, dst_addr, alias_addr,
- alias_port, dst_port, alias_port,
- link_type);
- }
-
- return(link);
-}
-
-
-struct alias_link *
-FindUdpTcpOut(struct in_addr src_addr,
- struct in_addr dst_addr,
- u_short src_port,
- u_short dst_port,
- u_char proto)
-{
- int link_type;
- struct alias_link *link;
-
- switch (proto)
- {
- case IPPROTO_UDP:
- link_type = LINK_UDP;
- break;
- case IPPROTO_TCP:
- link_type = LINK_TCP;
- break;
- default:
- return NULL;
- break;
- }
-
- link = FindLinkOut(src_addr, dst_addr, src_port, dst_port, link_type);
-
- if (link == NULL)
- {
- struct in_addr alias_addr;
-
- alias_addr = FindAliasAddress(src_addr);
- link = AddLink(src_addr, dst_addr, alias_addr,
- src_port, dst_port, GET_ALIAS_PORT,
- link_type);
- }
-
- return(link);
-}
-
-
-struct in_addr
-FindOriginalAddress(struct in_addr alias_addr)
-{
- struct alias_link *link;
-
- link = FindLinkIn(nullAddress, alias_addr,
- 0, 0, LINK_ADDR, 0);
- if (link == NULL)
- {
- newDefaultLink = 1;
- if (targetAddress.s_addr != 0)
- return targetAddress;
- else
- return alias_addr;
- }
- else
- {
- if (link->src_addr.s_addr == 0)
- return aliasAddress;
- else
- return link->src_addr;
- }
-}
-
-
-struct in_addr
-FindAliasAddress(struct in_addr original_addr)
-{
- struct alias_link *link;
-
- link = FindLinkOut(original_addr, nullAddress,
- 0, 0, LINK_ADDR);
- if (link == NULL)
- {
- return aliasAddress;
- }
- else
- {
- if (link->alias_addr.s_addr == 0)
- return aliasAddress;
- else
- return link->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()
-*/
-
-
-void
-SetFragmentAddr(struct alias_link *link, struct in_addr src_addr)
-{
- link->data.frag_addr = src_addr;
-}
-
-
-void
-GetFragmentAddr(struct alias_link *link, struct in_addr *src_addr)
-{
- *src_addr = link->data.frag_addr;
-}
-
-
-void
-SetFragmentPtr(struct alias_link *link, char *fptr)
-{
- link->data.frag_ptr = fptr;
-}
-
-
-void
-GetFragmentPtr(struct alias_link *link, char **fptr)
-{
- *fptr = link->data.frag_ptr;
-}
-
-
-void
-SetStateIn(struct alias_link *link, int state)
-{
- /* TCP input state */
- switch (state) {
- case ALIAS_TCP_STATE_DISCONNECTED:
- if (link->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED) {
- link->expire_time = TCP_EXPIRE_DEAD;
- } else {
- link->expire_time = TCP_EXPIRE_SINGLEDEAD;
- }
- link->data.tcp->state.in = state;
- break;
- case ALIAS_TCP_STATE_CONNECTED:
- link->expire_time = TCP_EXPIRE_CONNECTED;
- /*FALLTHROUGH*/
- case ALIAS_TCP_STATE_NOT_CONNECTED:
- link->data.tcp->state.in = state;
- break;
- default:
- abort();
- }
-}
-
-
-void
-SetStateOut(struct alias_link *link, int state)
-{
- /* TCP output state */
- switch (state) {
- case ALIAS_TCP_STATE_DISCONNECTED:
- if (link->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED) {
- link->expire_time = TCP_EXPIRE_DEAD;
- } else {
- link->expire_time = TCP_EXPIRE_SINGLEDEAD;
- }
- link->data.tcp->state.out = state;
- break;
- case ALIAS_TCP_STATE_CONNECTED:
- link->expire_time = TCP_EXPIRE_CONNECTED;
- /*FALLTHROUGH*/
- case ALIAS_TCP_STATE_NOT_CONNECTED:
- link->data.tcp->state.out = state;
- break;
- default:
- abort();
- }
-}
-
-
-int
-GetStateIn(struct alias_link *link)
-{
- /* TCP input state */
- return link->data.tcp->state.in;
-}
-
-
-int
-GetStateOut(struct alias_link *link)
-{
- /* TCP output state */
- return link->data.tcp->state.out;
-}
-
-
-struct in_addr
-GetOriginalAddress(struct alias_link *link)
-{
- if (link->src_addr.s_addr == 0)
- return aliasAddress;
- else
- return(link->src_addr);
-}
-
-
-struct in_addr
-GetDestAddress(struct alias_link *link)
-{
- return(link->dst_addr);
-}
-
-
-struct in_addr
-GetAliasAddress(struct alias_link *link)
-{
- if (link->alias_addr.s_addr == 0)
- return aliasAddress;
- else
- return link->alias_addr;
-}
-
-
-struct in_addr
-GetDefaultAliasAddress()
-{
- return aliasAddress;
-}
-
-
-void
-SetDefaultAliasAddress(struct in_addr alias_addr)
-{
- aliasAddress = alias_addr;
-}
-
-
-u_short
-GetOriginalPort(struct alias_link *link)
-{
- return(link->src_port);
-}
-
-
-u_short
-GetAliasPort(struct alias_link *link)
-{
- return(link->alias_port);
-}
-
-u_short
-GetDestPort(struct alias_link *link)
-{
- return(link->dst_port);
-}
-
-void
-SetAckModified(struct alias_link *link)
-{
-/* Indicate that ack numbers have been modified in a TCP connection */
- link->data.tcp->state.ack_modified = 1;
-}
-
-
-int
-GetAckModified(struct alias_link *link)
-{
-/* See if ack numbers have been modified */
- return link->data.tcp->state.ack_modified;
-}
-
-
-int
-GetDeltaAckIn(struct ip *pip, struct alias_link *link)
-{
-/*
-Find out how much the ack number has been altered for an incoming
-TCP packet. To do this, a circular list is 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 = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
- 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 = link->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 *link)
-{
-/*
-Find out how much the seq number has been altered for an outgoing
-TCP packet. To do this, a circular list is 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 = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
- 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 = link->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 *link, 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 = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
-
- 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 = link->data.tcp->state.index;
- link->data.tcp->ack[i] = x;
-
- i++;
- if (i == N_LINK_TCP_DATA)
- link->data.tcp->state.index = 0;
- else
- link->data.tcp->state.index = i;
-}
-
-void
-SetExpire(struct alias_link *link, int expire)
-{
- if (expire == 0)
- {
- link->flags &= ~LINK_PERMANENT;
- DeleteLink(link);
- }
- else if (expire == -1)
- {
- link->flags |= LINK_PERMANENT;
- }
- else if (expire > 0)
- {
- link->expire_time = expire;
- }
- else
- {
- fprintf(stderr, "PacketAlias/SetExpire(): ");
- fprintf(stderr, "error in expire parameter\n");
- }
-}
-
-void
-ClearCheckNewLink(void)
-{
- newDefaultLink = 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(void)
-{
- 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);
- timeStamp = tv.tv_sec;
-
- /* Compute number of spokes (output table link chains) to cover */
- n100 = LINK_TABLE_OUT_SIZE * 100 + houseKeepingResidual;
- n100 *= timeStamp - lastCleanupTime;
- n100 /= ALIAS_CLEANUP_INTERVAL_SECS;
-
- n = n100/100;
-
- /* Handle different cases */
- if (n > ALIAS_CLEANUP_MAX_SPOKES)
- {
- n = ALIAS_CLEANUP_MAX_SPOKES;
- lastCleanupTime = timeStamp;
- houseKeepingResidual = 0;
-
- for (i=0; i<n; i++)
- IncrementalCleanup();
- }
- else if (n > 0)
- {
- lastCleanupTime = timeStamp;
- houseKeepingResidual = n100 - 100*n;
-
- for (i=0; i<n; i++)
- IncrementalCleanup();
- }
- else if (n < 0)
- {
- fprintf(stderr, "PacketAlias/HouseKeeping(): ");
- fprintf(stderr, "something unexpected in time values\n");
- lastCleanupTime = timeStamp;
- houseKeepingResidual = 0;
- }
-}
-
-
-/* Init the log file and enable logging */
-static void
-InitPacketAliasLog(void)
-{
- if ((~packetAliasMode & PKT_ALIAS_LOG)
- && (monitorFile = fopen("/var/log/alias.log", "w")))
- {
- packetAliasMode |= PKT_ALIAS_LOG;
- fprintf(monitorFile,
- "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
- }
-}
-
-
-/* Close the log-file and disable logging. */
-static void
-UninitPacketAliasLog(void)
-{
- if (monitorFile) {
- fclose(monitorFile);
- monitorFile = NULL;
- }
- packetAliasMode &= ~PKT_ALIAS_LOG;
-}
-
-
-
-
-
-
-/* Outside world interfaces
-
--- "outside world" means other than alias*.c routines --
-
- PacketAliasRedirectPort()
- PacketAliasRedirectAddr()
- PacketAliasRedirectDelete()
- PacketAliasSetAddress()
- PacketAliasInit()
- PacketAliasUninit()
- PacketAliasSetMode()
-
-(prototypes in alias.h)
-*/
-
-/* Redirection from a specific public addr:port to a
- a private addr:port */
-struct alias_link *
-PacketAliasRedirectPort(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 *link;
-
- switch(proto)
- {
- case IPPROTO_UDP:
- link_type = LINK_UDP;
- break;
- case IPPROTO_TCP:
- link_type = LINK_TCP;
- break;
- default:
- fprintf(stderr, "PacketAliasRedirectPort(): ");
- fprintf(stderr, "only TCP and UDP protocols allowed\n");
- return NULL;
- }
-
- link = AddLink(src_addr, dst_addr, alias_addr,
- src_port, dst_port, alias_port,
- link_type);
-
- if (link != NULL)
- {
- link->flags |= LINK_PERMANENT;
- }
- else
- {
- fprintf(stderr, "PacketAliasRedirectPort(): "
- "call to AddLink() failed\n");
- }
-
- return link;
-}
-
-
-/* Static address translation */
-struct alias_link *
-PacketAliasRedirectAddr(struct in_addr src_addr,
- struct in_addr alias_addr)
-{
- struct alias_link *link;
-
- link = AddLink(src_addr, nullAddress, alias_addr,
- 0, 0, 0,
- LINK_ADDR);
-
- if (link != NULL)
- {
- link->flags |= LINK_PERMANENT;
- }
- else
- {
- fprintf(stderr, "PacketAliasRedirectAddr(): "
- "call to AddLink() failed\n");
- }
-
- return link;
-}
-
-
-void
-PacketAliasRedirectDelete(struct alias_link *link)
-{
-/* This is a dangerous function to put in the API,
- because an invalid pointer can crash the program. */
-
- deleteAllLinks = 1;
- DeleteLink(link);
- deleteAllLinks = 0;
-}
-
-
-void
-PacketAliasSetAddress(struct in_addr addr)
-{
- if (packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
- && aliasAddress.s_addr != addr.s_addr)
- CleanupAliasData();
-
- aliasAddress = addr;
-}
-
-
-void
-PacketAliasSetTarget(struct in_addr target_addr)
-{
- targetAddress = target_addr;
-}
-
-
-void
-PacketAliasInit(void)
-{
- int i;
- struct timeval tv;
- struct timezone tz;
- static int firstCall = 1;
-
- if (firstCall == 1)
- {
- gettimeofday(&tv, &tz);
- timeStamp = tv.tv_sec;
- lastCleanupTime = tv.tv_sec;
- houseKeepingResidual = 0;
-
- for (i=0; i<LINK_TABLE_OUT_SIZE; i++)
- linkTableOut[i] = NULL;
- for (i=0; i<LINK_TABLE_IN_SIZE; i++)
- linkTableIn[i] = NULL;
-
- atexit(PacketAliasUninit);
- firstCall = 0;
- }
- else
- {
- deleteAllLinks = 1;
- CleanupAliasData();
- deleteAllLinks = 0;
- }
-
- aliasAddress.s_addr = 0;
- targetAddress.s_addr = 0;
-
- icmpLinkCount = 0;
- udpLinkCount = 0;
- tcpLinkCount = 0;
- fragmentIdLinkCount = 0;
- fragmentPtrLinkCount = 0;
- sockCount = 0;
-
- cleanupIndex =0;
-
- packetAliasMode = PKT_ALIAS_SAME_PORTS
- | PKT_ALIAS_USE_SOCKETS
- | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
-}
-
-void
-PacketAliasUninit(void) {
- deleteAllLinks = 1;
- CleanupAliasData();
- deleteAllLinks = 0;
- UninitPacketAliasLog();
-#ifndef NO_FW_PUNCH
- UninitPunchFW();
-#endif
-}
-
-
-/* Change mode for some operations */
-unsigned int
-PacketAliasSetMode(
- 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(); /* Do the enable */
- } else
-/* _Disable_ logging? */
- if (~flags & mask & PKT_ALIAS_LOG) {
- UninitPacketAliasLog();
- }
-
-#ifndef NO_FW_PUNCH
-/* Start punching holes in the firewall? */
- if (flags & mask & PKT_ALIAS_PUNCH_FW) {
- InitPunchFW();
- } else
-/* Stop punching holes in the firewall? */
- if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
- UninitPunchFW();
- }
-#endif
-
-/* Other flags can be set/cleared without special action */
- packetAliasMode = (flags & mask) | (packetAliasMode & ~mask);
- return packetAliasMode;
-}
-
-
-int
-PacketAliasCheckNewLink(void)
-{
- return 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.
- ****************/
-
-/* Firewall include files */
-#include <sys/queue.h>
-#include <net/if.h>
-#include <netinet/ip_fw.h>
-#include <string.h>
-#include <err.h>
-
-static void ClearAllFWHoles(void);
-
-static int fireWallBaseNum; /* The first firewall entry free for our use */
-static int fireWallNumNums; /* How many entries can we use? */
-static int fireWallActiveNum; /* Which entry did we last use? */
-static char *fireWallField; /* bool array for entries */
-
-#define fw_setfield(field, num) \
-do { \
- (field)[num] = 1; \
-} /*lint -save -e717 */ while(0) /*lint -restore */
-#define fw_clrfield(field, num) \
-do { \
- (field)[num] = 0; \
-} /*lint -save -e717 */ while(0) /*lint -restore */
-#define fw_tstfield(field, num) ((field)[num])
-
-void
-PacketAliasSetFWBase(unsigned int base, unsigned int num) {
- fireWallBaseNum = base;
- fireWallNumNums = num;
-}
-
-static void
-InitPunchFW(void) {
- fireWallField = malloc(fireWallNumNums);
- if (fireWallField) {
- memset(fireWallField, 0, fireWallNumNums);
- if (fireWallFD < 0) {
- fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
- }
- ClearAllFWHoles();
- fireWallActiveNum = fireWallBaseNum;
- }
-}
-
-static void
-UninitPunchFW(void) {
- ClearAllFWHoles();
- if (fireWallFD >= 0)
- close(fireWallFD);
- fireWallFD = -1;
- if (fireWallField)
- free(fireWallField);
- fireWallField = NULL;
- packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
-}
-
-/* Make a certain link go through the firewall */
-void
-PunchFWHole(struct alias_link *link) {
- int r; /* Result code */
- struct ip_fw rule; /* On-the-fly built rule */
- int fwhole; /* Where to punch hole */
-
-/* Don't do anything unless we are asked to */
- if ( !(packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
- fireWallFD < 0 ||
- link->link_type != LINK_TCP ||
- !link->data.tcp)
- return;
-
- memset(&rule, 0, sizeof rule);
-
-/** Build rule **/
-
- /* Find empty slot */
- for (fwhole = fireWallActiveNum;
- fwhole < fireWallBaseNum + fireWallNumNums &&
- fw_tstfield(fireWallField, fwhole);
- fwhole++)
- ;
- if (fwhole >= fireWallBaseNum + fireWallNumNums ||
- fw_tstfield(fireWallField, fwhole)) {
- for (fwhole = fireWallBaseNum;
- fwhole < fireWallActiveNum &&
- fw_tstfield(fireWallField, fwhole);
- fwhole++)
- ;
- if (fwhole == fireWallActiveNum) {
- /* No rule point empty - we can't punch more holes. */
- fireWallActiveNum = fireWallBaseNum;
- fprintf(stderr, "libalias: Unable to create firewall hole!\n");
- return;
- }
- }
- /* Start next search at next position */
- fireWallActiveNum = fwhole+1;
-
- /* Build generic part of the two rules */
- rule.fw_number = fwhole;
- rule.fw_nports = 1; /* Number of source ports; dest ports follow */
- rule.fw_flg = IP_FW_F_ACCEPT;
- 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(link);
- rule.fw_dst = GetDestAddress(link);
- rule.fw_uar.fw_pts[0] = ntohs(GetOriginalPort(link));
- rule.fw_uar.fw_pts[1] = ntohs(GetDestPort(link));
-
- /* 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);
- if (r)
- err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
- rule.fw_src = GetDestAddress(link);
- rule.fw_dst = GetOriginalAddress(link);
- rule.fw_uar.fw_pts[0] = ntohs(GetDestPort(link));
- rule.fw_uar.fw_pts[1] = ntohs(GetOriginalPort(link));
- r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule);
- if (r)
- err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
- }
-/* Indicate hole applied */
- link->data.tcp->fwhole = fwhole;
- fw_setfield(fireWallField, fwhole);
-}
-
-/* Remove a hole in a firewall associated with a particular alias
- link. Calling this too often is harmless. */
-static void
-ClearFWHole(struct alias_link *link) {
- if (link->link_type == LINK_TCP && link->data.tcp) {
- int fwhole = link->data.tcp->fwhole; /* Where is the firewall hole? */
- struct ip_fw rule;
-
- if (fwhole < 0)
- return;
-
- memset(&rule, 0, sizeof rule);
- rule.fw_number = fwhole;
- while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule))
- ;
- fw_clrfield(fireWallField, fwhole);
- link->data.tcp->fwhole = -1;
- }
-}
-
-/* Clear out the entire range dedicated to firewall holes. */
-static void
-ClearAllFWHoles(void) {
- struct ip_fw rule; /* On-the-fly built rule */
- int i;
-
- if (fireWallFD < 0)
- return;
-
- memset(&rule, 0, sizeof rule);
- for (i = fireWallBaseNum; i < fireWallBaseNum + fireWallNumNums; i++) {
- rule.fw_number = i;
- while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule))
- ;
- }
- memset(fireWallField, 0, fireWallNumNums);
-}
-#endif
diff --git a/sys/netinet/libalias/alias_ftp.c b/sys/netinet/libalias/alias_ftp.c
deleted file mode 100644
index c6d449d05723..000000000000
--- a/sys/netinet/libalias/alias_ftp.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- Alias_ftp.c performs special processing for FTP sessions under
- TCP. Specifically, when a PORT command from the client side
- 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 PORT command 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 PORT command 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.
-
-
- This software is placed into the public domain with no restrictions
- on its distribution.
-
- 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)
- Differental 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
- withing the packet alising module.
-
- See HISTORY file for record of revisions.
-*/
-
-/* Includes */
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-
-#include "alias_local.h"
-
-static void NewFtpPortCommand(struct ip *, struct alias_link *, struct in_addr, u_short, int);
-
-
-
-void
-AliasHandleFtpOut(
-struct ip *pip, /* IP packet to examine/patch */
-struct alias_link *link, /* The link to go through (aliased port) */
-int maxpacketsize /* The maximum size this packet can grow to (including headers) */)
-{
- int hlen, tlen, dlen;
- struct in_addr true_addr;
- u_short true_port;
- char *sptr;
- struct tcphdr *tc;
-
-/* Calculate data length of TCP packet */
- tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
- hlen = (pip->ip_hl + tc->th_off) << 2;
- tlen = ntohs(pip->ip_len);
- dlen = tlen - hlen;
-
-/* Return is data length is too long or too short */
- if (dlen<10 || dlen>80)
- return;
-
-/* Place string pointer and beginning of data */
- sptr = (char *) pip;
- sptr += hlen;
-
-/* Parse through string using state diagram method */
- {
- char ch, zero;
- int i, state;
- u_long a1, a2, a3, a4;
- u_short p1, p2;
-
- a1=0; a2=0; a3=0; a4=0; p1=0; p2=0;
- zero = '0';
- state=-4;
- for (i=0; i<dlen; i++)
- {
- ch = sptr[i];
- switch (state)
- {
- case -4: if (ch == 'P') state=-3; else return; break;
- case -3: if (ch == 'O') state=-2; else return; break;
- case -2: if (ch == 'R') state=-1; else return; break;
- case -1: if (ch == 'T') state= 0; else return; break;
-
- case 0 :
- if (isdigit(ch)) {a1=ch-zero; state=1 ;} break;
- case 1 :
- if (isdigit(ch)) a1=10*a1+ch-zero; else state=2 ; break;
- case 2 :
- if (isdigit(ch)) {a2=ch-zero; state=3 ;} break;
- case 3 :
- if (isdigit(ch)) a2=10*a2+ch-zero; else state=4 ; break;
- case 4 :
- if (isdigit(ch)) {a3=ch-zero; state=5 ;} break;
- case 5 :
- if (isdigit(ch)) a3=10*a3+ch-zero; else state=6 ; break;
- case 6 :
- if (isdigit(ch)) {a4=ch-zero; state=7 ;} break;
- case 7 :
- if (isdigit(ch)) a4=10*a4+ch-zero; else state=8 ; break;
- case 8 :
- if (isdigit(ch)) {p1=ch-zero; state=9 ;} break;
- case 9 :
- if (isdigit(ch)) p1=10*p1+ch-zero; else state=10; break;
- case 10:
- if (isdigit(ch)) {p2=ch-zero; state=11;} break;
- case 11:
- if (isdigit(ch)) p2=10*p2+ch-zero; break;
- }
- }
-
- if (state == 11)
- {
- true_port = htons((p1<<8) + p2);
- true_addr.s_addr = htonl((a1<<24) + (a2<<16) +(a3<<8) + a4);
- NewFtpPortCommand(pip, link, true_addr, true_port, maxpacketsize);
- }
- }
-}
-
-static void
-NewFtpPortCommand(struct ip *pip,
- struct alias_link *link,
- struct in_addr true_addr,
- u_short true_port,
- int maxpacketsize)
-{
- struct alias_link *ftp_link;
-
-/* Establish link to address and port found in PORT command */
- ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link),
- true_port, 0, IPPROTO_TCP);
-
- if (ftp_link != NULL)
- {
- int slen, hlen, tlen, dlen;
- struct tcphdr *tc;
-
-#ifndef NO_FW_PUNCH
-/* Punch hole in firewall */
- PunchFWHole(ftp_link);
-#endif
-
-/* Calculate data length of TCP packet */
- tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
- hlen = (pip->ip_hl + tc->th_off) << 2;
- tlen = ntohs(pip->ip_len);
- dlen = tlen - hlen;
-
-/* Create new PORT command */
- {
- char stemp[80];
- 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(link);
- ptr = (u_char *) &alias_address.s_addr;
- a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
-
-/* Decompose alias port into pair format */
- alias_port = GetAliasPort(ftp_link);
- ptr = (char *) &alias_port;
- p1 = *ptr++; p2=*ptr;
-
-/* Generate command string */
- sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
- a1,a2,a3,a4,p1,p2);
-
-/* Save string length for IP header modification */
- slen = strlen(stemp);
-
-/* Copy into IP packet */
- sptr = (char *) pip; sptr += hlen;
- strncpy(sptr, stemp, maxpacketsize-hlen);
- }
-
-/* Save information regarding modified seq and ack numbers */
- {
- int delta;
-
- SetAckModified(link);
- delta = GetDeltaSeqOut(pip, link);
- AddSeq(pip, link, 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
- {
- fprintf(stderr,
- "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
- }
-}
diff --git a/sys/netinet/libalias/alias_irc.c b/sys/netinet/libalias/alias_irc.c
deleted file mode 100644
index 910e9343404a..000000000000
--- a/sys/netinet/libalias/alias_irc.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/* 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
-
- This software is placed into the public domain with no restrictions
- on its distribution.
-
- Initial version: Eivind Eklund <perhaps@yes.no> (ee) 97-01-29
-
- Version 2.1: May, 1997 (cjm)
- Very minor changes to conform with
- local/global/function naming conventions
- withing the packet alising module.
-*/
-
-/* Includes */
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-#include <limits.h>
-
-#include "alias_local.h"
-
-/* Local defines */
-#define DBprintf(a)
-
-
-void
-AliasHandleIrcOut(struct ip *pip, /* IP packet to examine */
- struct alias_link *link, /* 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 *) ((char *) pip + (pip->ip_hl << 2));
- 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<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 :) */
- int copyat = i; /* Same */
- 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_link;
- struct in_addr destaddr;
-
-
- true_port = htons(org_port);
- true_addr.s_addr = htonl(org_addr);
- destaddr.s_addr = 0;
-
- /* Steal the FTP_DATA_PORT - it doesn't really matter, and this
- would probably allow it through at least _some_
- firewalls. */
- dcc_link = FindUdpTcpOut (true_addr,
- destaddr,
- true_port,
- 0, IPPROTO_TCP);
- DBprintf(("Got a DCC link\n"));
- if ( dcc_link ) {
- struct in_addr alias_address; /* Address from aliasing */
- u_short alias_port; /* Port given by aliasing */
-
-#ifndef NO_FW_PUNCH
- /* Generate firewall hole as appropriate */
- PunchFWHole(dcc_link);
-#endif
-
- alias_address = GetAliasAddress(link);
- iCopy += snprintf(&newpacket[iCopy],
- sizeof(newpacket)-iCopy,
- "%lu ", (u_long)htonl(alias_address.s_addr));
- if( iCopy >= sizeof(newpacket) ) { /* Truncated/fit exactly - bad news */
- DBprintf(("DCC constructed packet overflow.\n"));
- goto lBAD_CTCP;
- }
- alias_port = GetAliasPort(dcc_link);
- iCopy += snprintf(&newpacket[iCopy],
- sizeof(newpacket)-iCopy,
- "%u", htons(alias_port) );
- /* 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(link);
- delta = GetDeltaSeqOut(pip, link);
- AddSeq(pip, link, 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/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h
deleted file mode 100644
index 38462810733a..000000000000
--- a/sys/netinet/libalias/alias_local.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* -*- mode: c; tab-width: 3; c-basic-offset: 3; -*-
- 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 is intended to be used only within
- the aliasing software. Outside world interfaces are defined
- in alias.h
-
- This software is placed into the public domain with no restrictions
- on its distribution.
-
- Initial version: August, 1996 (cjm)
-
- <updated several times by original author and Eivind Eiklund>
-*/
-#ifndef ALIAS_LOCAL_H
-#define ALIAS_LOCAL_H
-
-extern int packetAliasMode;
-
-struct alias_link;
-
-/* General utilities */
-u_short IpChecksum(struct ip *);
-u_short TcpChecksum(struct ip *);
-void DifferentialChecksum(u_short *, u_short *, u_short *, int);
-
-/* Internal data access */
-struct alias_link *
-FindIcmpIn(struct in_addr, struct in_addr, u_short);
-
-struct alias_link *
-FindIcmpOut(struct in_addr, struct in_addr, u_short);
-
-struct alias_link *
-FindFragmentIn1(struct in_addr, struct in_addr, u_short);
-
-struct alias_link *
-FindFragmentIn2(struct in_addr, struct in_addr, u_short);
-
-struct alias_link *
-AddFragmentPtrLink(struct in_addr, u_short);
-
-struct alias_link *
-FindFragmentPtr(struct in_addr, u_short);
-
-struct alias_link *
-FindUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
-
-struct alias_link *
-FindUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
-
-struct in_addr
-FindOriginalAddress(struct in_addr);
-
-struct in_addr
-FindAliasAddress(struct in_addr);
-
-/* External data access/modification */
-void GetFragmentAddr(struct alias_link *, struct in_addr *);
-void SetFragmentAddr(struct alias_link *, struct in_addr);
-void GetFragmentPtr(struct alias_link *, char **);
-void SetFragmentPtr(struct alias_link *, char *);
-void SetStateIn(struct alias_link *, int);
-void SetStateOut(struct alias_link *, int);
-int GetStateIn(struct alias_link *);
-int GetStateOut(struct alias_link *);
-struct in_addr GetOriginalAddress(struct alias_link *);
-struct in_addr GetDestAddress(struct alias_link *);
-struct in_addr GetAliasAddress(struct alias_link *);
-struct in_addr GetDefaultAliasAddress(void);
-void SetDefaultAliasAddress(struct in_addr);
-u_short GetOriginalPort(struct alias_link *);
-u_short GetAliasPort(struct alias_link *);
-void SetAckModified(struct alias_link *);
-int GetAckModified(struct alias_link *);
-int GetDeltaAckIn(struct ip *, struct alias_link *);
-int GetDeltaSeqOut(struct ip *, struct alias_link *);
-void AddSeq(struct ip *, struct alias_link *, int);
-void SetExpire(struct alias_link *, int);
-void ClearCheckNewLink(void);
-#ifndef NO_FW_PUNCH
-void PunchFWHole(struct alias_link *);
-#endif
-
-
-/* Housekeeping function */
-void HouseKeeping(void);
-
-/* Tcp specfic routines */
-/*lint -save -library Suppress flexelint warnings */
-void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
-void AliasHandleIrcOut(struct ip *pip, struct alias_link *link, int maxsize );
-int AliasHandleUdpNbt(struct ip *, struct alias_link *, struct in_addr *, u_short);
-int AliasHandleUdpNbtNS(struct ip *, struct alias_link *, struct in_addr *, u_short *, struct in_addr *, u_short *);
-void AliasHandleCUSeeMeOut(struct ip *, struct alias_link *);
-void AliasHandleCUSeeMeIn(struct ip *, struct in_addr);
-
-
-
-enum alias_tcp_state {
- ALIAS_TCP_STATE_NOT_CONNECTED,
- ALIAS_TCP_STATE_CONNECTED,
- ALIAS_TCP_STATE_DISCONNECTED
-};
-
-/*lint -restore */
-#endif /* defined(ALIAS_LOCAL_H) */
diff --git a/sys/netinet/libalias/alias_nbt.c b/sys/netinet/libalias/alias_nbt.c
deleted file mode 100644
index cd07431f5cbf..000000000000
--- a/sys/netinet/libalias/alias_nbt.c
+++ /dev/null
@@ -1,713 +0,0 @@
-/*
- * Written by Atsushi Murai <amurai@spec.co.jp>
- *
- * Copyright (C) 1998, System Planning and Engineering Co. All rights reserverd.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the System Planning and Engineering Co. The name of the
- * SPEC may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Id: alias_nbt.c,v 1.1 1998/05/24 03:03:10 amurai Exp $
- *
- * TODO:
- * oClean up.
- * oConsidering for word alignment for other platform.
- */
-/*
- alias_nbt.c performs special processing for NetBios over TCP/IP
- sessions by UDP.
-
- Initial version: May, 1998 (Atsushi Murai <amurai@spec.co.jp>)
-
- See HISTORY file for record of revisions.
-*/
-
-/* Includes */
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-
-#include "alias_local.h"
-
-#define ADJUST_CHECKSUM(acc, cksum) { \
- 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; \
- } \
-}
-
-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
-
-/*******************************************************************
- * copy an IP address from one buffer to another *
- *******************************************************************/
-void putip(void *dest,void *src)
-{
- memcpy(dest,src,4);
-}
-
-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???=%0x\n", rcode );
-
- }
-}
-
-
-/* Handling Name field */
-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 ip *pip, /* IP packet to examine/patch */
- struct alias_link *link,
- struct in_addr *alias_address,
- u_short alias_port
-) {
- struct udphdr * uh;
- NbtDataHeader *ndh;
- u_char *p = NULL;
- char *pmax;
-
- /* Calculate data length of UDP packet */
- uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
- pmax = (char *)uh + ntohs( uh->uh_ulen );
-
- ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
- 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 a 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;
-
-u_char *
-AliasHandleQuestion(
- u_short count,
- NBTNsQuestion *q,
- char *pmax,
- NBTArguments *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:
- printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
- 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;
-
-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;
-
-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;
-
-u_char *
-AliasHandleResourceNULL(
- NBTNsResource *q,
- char *pmax,
- NBTArguments *nbtarg)
-{
- NBTNsResourceNULL *n;
- u_short bcount;
-
- 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);
-}
-
-u_char *
-AliasHandleResourceNS(
- NBTNsResource *q,
- char *pmax,
- NBTArguments *nbtarg)
-{
- NBTNsResourceNULL *n;
- u_short bcount;
-
- 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;
-
-u_char *
-AliasHandleResourceNBSTAT(
- NBTNsResource *q,
- char *pmax,
- NBTArguments *nbtarg)
-{
- NBTNsResourceNBSTAT *n;
- u_short bcount;
-
- 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);
-}
-
-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:
- printf(
- "\nUnknown Type of Resource %0x\n",
- ntohs(q->type)
- );
- break;
- }
- count--;
- }
- fflush(stdout);
- return ((u_char *)q);
-}
-
-int AliasHandleUdpNbtNS(
- struct ip *pip, /* IP packet to examine/patch */
- struct alias_link *link,
- 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;
-
- /* 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 *) ((char *) pip + (pip->ip_hl << 2));
- nbtarg.uh_sum = &(uh->uh_sum);
- nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
- 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/sys/netinet/libalias/alias_old.c b/sys/netinet/libalias/alias_old.c
deleted file mode 100644
index 3f634d448411..000000000000
--- a/sys/netinet/libalias/alias_old.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- This file can be considered a junk pile of old functions that
- are either obsolete or have had their names changed. In the
- transition from alias2.1 to alias2.2, all the function names
- were rationalized so that they began with "PacketAlias..."
-
- These functions are included for backwards compatibility.
-*/
-
-#include <sys/types.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include "alias.h"
-#include "alias_local.h"
-
-void
-InitPacketAlias(void)
-{
- PacketAliasInit();
-}
-
-void
-SetPacketAliasAddress(struct in_addr addr)
-{
- PacketAliasSetAddress(addr);
-}
-
-unsigned int
-SetPacketAliasMode(unsigned int flags, unsigned int mask)
-{
- return PacketAliasSetMode(flags, mask);
-}
-
-int
-PacketAliasPermanentLink(struct in_addr src_addr, u_short src_port,
- struct in_addr dst_addr, u_short dst_port,
- u_short alias_port, u_char proto)
-{
- struct alias_link *link;
- struct in_addr null_address;
-
- null_address.s_addr = 0;
- link = PacketAliasRedirectPort(src_addr, src_port,
- dst_addr, dst_port,
- null_address, alias_port,
- proto);
-
- if (link == NULL)
- return -1;
- else
- return 0;
-}
-
-int
-SaveFragmentPtr(char *ptr)
-{
- return PacketAliasSaveFragment(ptr);
-}
-
-char *
-GetNextFragmentPtr(char *ptr)
-{
- return PacketAliasGetFragment(ptr);
-}
-
-void
-FragmentAliasIn(char *header, char *fragment)
-{
- PacketAliasFragmentIn(header, fragment);
-}
-
-u_short
-InternetChecksum(u_short *ptr, int len)
-{
- return PacketAliasInternetChecksum(ptr, len);
-}
diff --git a/sys/netinet/libalias/alias_util.c b/sys/netinet/libalias/alias_util.c
deleted file mode 100644
index fe0765312018..000000000000
--- a/sys/netinet/libalias/alias_util.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- Alias_util.h 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 workd is filled with the proper value,
-then these routines will give a result of zero (useful for testing
-purposes);
-*/
-
-#include <sys/types.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-
-#include "alias.h"
-#include "alias_local.h"
-
-u_short
-PacketAliasInternetChecksum(u_short *ptr, int nbytes)
-{
- int sum, oddbyte;
-
- sum = 0;
- while (nbytes > 1)
- {
- sum += *ptr++;
- nbytes -= 2;
- }
- if (nbytes == 1)
- {
- oddbyte = 0;
- *((u_char *) &oddbyte) = *(u_char *) ptr;
- 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 *) ((char *) pip + nhdr);
- 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) = *(u_char *) ptr;
- 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, u_short *new, u_short *old, int n)
-{
- int i;
- int accumulate;
-
- 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/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3
deleted file mode 100644
index f9b36e6c6d71..000000000000
--- a/sys/netinet/libalias/libalias.3
+++ /dev/null
@@ -1,768 +0,0 @@
-.Dd July, 1997
-.Dt "libalias" 3
-.Os
-.Sh NAME
-.Nm "libalias"
-Packet Aliasing Library. A collection of
-functions for aliasing and de-aliasing
-of IP packets, intended for masquerading and
-network address translation (NAT).
-
-.Sh SYNOPSIS
-.Fd #include <sys/types.h>
-.Fd #include <netinet/in.h>
-.Fd #include <alias.h>
-
-Function prototypes are given in the main body
-of the text.
-
-.Sh CONTENTS
-.Bd -literal -offset left
-1. Introduction
-2. Initialization and Control
- 2.1 PacketAliasInit()
- 2.2 PacketAliasUninit()
- 2.3 PacketAliasSetAddress()
- 2.4 PacketAliasSetMode()
- 2.5 PacketAliasSetFWBase()
-3. Packet Handling
- 3.1 PacketAliasIn()
- 3.2 PacketAliasOut()
-4. Port and Address Redirection
- 4.1 PacketAliasRedirectPort()
- 4.2 PacketAliasRedirectAddr()
- 4.3 PacketAliasRedirectDelete()
-5. Fragment Handling
- 5.1 PacketAliasSaveFragment()
- 5.2 PacketAliasGetFragment()
- 5.3 PacketAliasFragmentIn()
-6. Miscellaneous Functions
- 6.1 PacketAliasSetTarget()
- 6.2 PacketAliasCheckNewLink()
- 6.3 PacketAliasInternetChecksum()
-7. Authors
-8. Acknowledgments
-
-Appendix A: Conceptual Background
- A.1 Aliasing Links
- A.2 Static and Dynamic Links
- A.3 Partially Specified Links
- A.4 Dynamic Link Creation
-.Ed
-
-.Sh 1. 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.
-
-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.
-
-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 2. Initialization and Control
-Two specific functions, PacketAliasInit()
-and PacketAliasSetAddress(), must always be
-called before any packet handling may be
-performed. In addition, the operating mode
-of the packet aliasing engine can be customized
-by calling PacketAliasSetMode().
-.Ss 2.1 PacketAliasInit()
-
-.Ft void
-.Fn PacketAliasInit "void"
-
-This function has no argument or return
-value and is used to initialize internal
-data structures. The following mode bits
-are always set after calling
-PacketAliasInit(). See section 2.3 for
-the meaning of these mode bits.
-.Bd -literal -offset indent
- PKT_ALIAS_USE_SAME_PORTS
- PKT_ALIAS_USE_SOCKETS
- PKT_ALIAS_RESET_ON_ADDR_CHANGE
-
-.Ed
-This function will always return the packet
-aliasing engine to the same initial state.
-PacketAliasSetAddress() must be called afterwards,
-and any desired changes from the default mode
-bits listed above require a call to
-PacketAliasSetMode().
-
-It is mandatory that this function be called
-at the beginning of a program prior to any
-packet handling.
-.Ss 2.2 PacketAliasUninit()
-
-.Ft void
-.Fn PacketAliasUninit "void"
-
-This function has no argument or return
-value and is used to clear any resources
-attached to internal data structures.
-
-This functions should be called when a
-program stop using the aliasing engine;
-it do, among other things, clear out any
-firewall holes. To provide backwards
-compatibility and extra security, it is
-added to the atexit() chain by
-PacketAliasInit(). Calling it multiple
-times is harmless.
-.Ss 2.3 PacketAliasSetAddress()
-
-.Ft void
-.Fn PacketAliasSetAddress "struct in_addr addr"
-
-This function sets the source address to which
-outgoing packets from the local area network
-are aliased. All outgoing packets are remapped
-to this address unless overridden by a static
-address mapping established by
-PacketAliasRedirectAddr().
-
-If the 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, as if
-PacketAliasReset() were called. This is useful
-for interfaces such as ppp where the IP
-address may or may not change on successive
-dial-up attempts.
-
-If the 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).
-
-It is mandatory that this function be called
-prior to any packet handling.
-.Ss 2.4 PacketAliasSetMode()
-
-.Ft unsigned int
-.Fn PacketAliasSetMode "unsigned int mode" "unsigned int mask"
-
-This function sets or clears mode bits
-according to the value of
-.Em mode .
-Only bits marked in
-.Em mask
-are affected. The following mode bits are
-defined in alias.h:
-.Bl -hang -offset left
-.It PKT_ALIAS_LOG.
-Enables logging /var/log/alias.log. The log file
-shows total numbers of links (icmp, tcp, udp) each
-time an aliasing link is created or deleted. Mainly
-useful for debugging when the log file is viewed
-continuously with "tail -f".
-.It 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 (PacketAliasIn() return code
-PKT_ALIAS_IGNORED) 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 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
-number. This can be done as long as the
-quintuple (proto, alias addr, alias port,
-remote addr, remote port) is unique. If a
-conflict exists, an new aliasing port number is
-chosen even if this mode bit is set.
-.It PKT_ALIAS_USE_SOCKETS.
-This bit should be set when the 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 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
-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 doesn't
-need to be passed through the packet aliasing
-engine.
-.It PKT_ALIAS_RESET_ON_ADDR_CHANGE.
-When this mode bit is set and
-PacketAliasSetAddress() 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 ppp links
-where the interface address can sometimes
-change or remain the same between dial-ups.
-If this mode bit is not set, it the link table
-will never be reset in the event of an
-address change.
-.It PKT_ALIAS_PUNCH_FW.
-This option make libalias `punch holes' in an
-ipfw 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 use it die. To cater for
-unexpected death of a program using libalias (e.g
-kill -9), changing the state of the flag will
-clear the entire ipfw range allocated for holes.
-This will also happen on the initial call to
-PacketAliasSetFWBase(). This call must happen
-prior to setting this flag.
-
-.El
-
-.Ss 2.5 PacketAliasSetFWBase()
-
-.Ft void
-.Fn PacketAliasSetFWBase "unsigned int base" "unsigned int num"
-
-Set IPFW range allocated for punching firewall holes (with the
-PKT_ALIAS_PUNCH_FW flag). The range will be cleared for all rules on
-initialization.
-
-.Sh 3. Packet Handling
-The packet handling functions are used to
-modify incoming (remote->local) and outgoing
-(local->remote) packets. The calling program
-is responsible for receiving and sending
-packets via network interfaces.
-
-Along with PacketAliasInit() and PacketAliasSetAddress(),
-the two packet handling functions, PacketAliasIn()
-and PacketAliasOut(), comprise minimal set of functions
-needed for a basic IP masquerading implementation.
-.Ss 3.1 PacketAliasIn()
-
-.Ft int
-.Fn PacketAliasIn "char *buffer" "int maxpacketsize"
-
-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
-.Em buffer ,
-and
-.Em maxpacketsize
-indicates the size of the data structure containing
-the packet and should be at least as large as the
-actual packet size.
-
-Return codes:
-.Bl -hang -offset left
-.It PKT_ALIAS_ERROR.
-An internal error within the packet aliasing
-engine occurred.
-.It PKT_ALIAS_OK.
-The packet aliasing process was successful.
-.It PKT_ALIAS_IGNORED.
-The packet was ignored and not de-aliased.
-This can happen if the protocal is unrecognized,
-possibly an ICMP message type is not handled or
-if incoming packets for new connections are being
-ignored (see PKT_ALIAS_DENY_INCOMING in section
-2.2).
-.It 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 PacketAliasSaveFragment()
-until a header fragment is found.
-.It 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 PacketAliasGetFragment() and de-alias
-them with PacketAliasFragmentIn().
-.El
-.Ss 3.2 PacketAliasOut()
-
-.Ft int
-.Fn PacketAliasOut "char *buffer" "int maxpacketsize"
-
-An outgoing packet coming from the local network
-to a remote machine is aliased by this function.
-The IP packet is pointed to by
-.Em buffer r,
-and
-.Em 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 have to be
-modified and can account for changes in packet
-length. Well known examples of such protocols
-are FTP and IRC DCC.
-
-Return codes:
-.Bl -hang -offset left
-.It PKT_ALIAS_ERROR.
-An internal error within the packet aliasing
-engine occurred.
-.It PKT_ALIAS_OK.
-The packet aliasing process was successful.
-.It PKT_ALIAS_IGNORED.
-The packet was ignored and not de-aliased.
-This can happen if the protocal is unrecognized,
-or possibly an ICMP message type is not handled.
-.El
-
-.Sh 4. 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.
-.Ss 4.1 PacketAliasRedirectPort()
-
-.Ft struct alias_link *
-.Fo PacketAliasRedirectPort
-.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
-
-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
-.Em proto
-can be either IPPROTO_TCP or IPPROTO_UDP, as
-defined in <netinet/in.h>.
-
-If
-.Em local_addr
-or
-.Em alias_addr
-is zero, this indicates that the packet aliasing
-address as established by PacketAliasSetAddress()
-is to be used. Even if PacketAliasAddress() is
-called to change the address after PacketAliasRedirectPort()
-is called, a zero reference will track this change.
-
-If
-.Em remote_addr
-is zero, this indicates to redirect packets from
-any remote address. Likewise, if
-.Em 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 be sometimes be useful for firewalling.
-If two calls to PacketAliasRedirectPort() overlap in
-their address/port specifications, then the most recent
-call will have precedence.
-
-This function returns a pointer which can subsequently
-be used by PacketAliasRedirectDelete(). If NULL is
-returned, then the function call did not complete
-successfully.
-
-All port numbers are in network address byte order,
-so it is necessary to use htons() 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
-.Em struct in_addr
-data type.
-.Ss 4.2 PacketAliasRedirectAddr()
-
-.Ft struct alias_link *
-.Fo PacketAliasRedirectAddr
-.Fa "struct in_addr local_addr"
-.Fa "struct in_addr alias_addr"
-.Fc
-
-This function desgnates that all incoming
-traffic to
-.Em alias_addr
-be redirected to
-.Em local_addr.
-Similarly, all outgoing traffic from
-.Em local_addr
-is aliased to
-.Em alias_addr .
-
-If
-.Em local_addr
-or
-.Em alias_addr
-is zero, this indicates that the packet aliasing
-address as established by PacketAliasSetAddress()
-is to be used. Even if PacketAliasAddress() is
-called to change the address after PacketAliasRedirectAddr()
-is called, a zero reference will track this change.
-
-If subsequent calls to PacketAliasRedirectAddr()
-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,
-but new traffic all of the local machines designated
-in the several function calls will be aliased to
-the same address. Consider the following example:
-.Bd -literal -offset left
- PacketAliasRedirectAddr(inet_aton("192.168.0.2"),
- inet_aton("141.221.254.101"));
- PacketAliasRedirectAddr(inet_aton("192.168.0.3"),
- inet_aton("141.221.254.101"));
- PacketAliasRedirectAddr(inet_aton("192.168.0.4"),
- inet_aton("141.221.254.101"));
-.Ed
-
-Any outgoing connections such as telnet or ftp
-from 192.168.0.2, 102.168.0.3, 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.
-
-Any calls to PacketAliasRedirectPort() will
-have precedence over address mappings designated
-by PacketAliasRedirectAddr().
-
-This function returns a pointer which can subsequently
-be used by PacketAliasRedirectDelete(). If NULL is
-returned, then the function call did not complete
-successfully.
-.Ss 4.3 PacketAliasRedirectDelete()
-
-.Ft void
-.Fn PacketAliasRedirectDelete "struct alias_link *ptr"
-
-This function will delete a specific static redirect
-rule entered by PacketAliasRedirectPort() or
-PacketAliasRedirectAddr(). The parameter
-.Em ptr
-is the pointer returned by either of the redirection
-functions. If an invalid pointer is passed to
-PacketAliasRedirectDelete(), then a program crash
-or unpredictable operation could result, so it is
-necessary to be careful using this function.
-
-.Sh 5. Fragment Handling
-The functions in this section are used to deal with
-incoming fragments.
-
-Outgoing fragments are handled within PacketAliasOut()
-by changing the address according to any
-applicable mapping set by PacketAliasRedirectAddress(),
-or the default aliasing address set by
-PacketAliasSetAddress().
-
-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.
-.Ss 5.1 PacketAliasSaveFragment()
-
-.Ft int
-.Fn PacketAliasSaveFragment "char *ptr"
-
-When PacketAliasIn() returns
-PKT_ALIAS_UNRESOLVED_FRAGMENT, this
-function can be used to save the pointer to
-the unresolved fragment.
-
-It is implicitly assumed that
-.Em ptr
-points to a block of memory allocated by
-malloc(). 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.]
-
-This function returns PKT_ALIAS_OK if it
-was successful and PKT_ALIAS_ERROR if there
-was an error.
-.Ss 5.2 PacketAliasGetNextFragment()
-
-.Ft char *
-.Fn PacketAliasGetFragment "char *buffer"
-
-This function can be used to retrieve fragment
-pointers saved by PacketAliasSaveFragment().
-The IP header fragment pointed to by
-Em buffer
-is the header fragment indicated when
-PacketAliasIn() returns PKT_ALIAS_FOUND_HEADER_FRAGMENT.
-Once a a fragment pointer is retrieved, it
-becomes the calling program's responsibility
-to free the dynamically allocated memory for
-the fragment.
-
-PacketAliasGetFragment() can be called
-sequentially until there are no more fragments
-available, at which time it returns NULL.
-.Ss 5.3 PacketAliasFragmentIn()
-
-.Ft void
-.Fn PacketAliasFragmentIn "char *header" "char *fragment"
-
-When a fragment is retrieved with
-PacketAliasGetFragment(), it can then be
-de-aliased with a call to PacketAliasFragmentIn().
-.Em header
-is the pointer to a header fragment used as a
-template, and
-.Em fragment
-is the pointer to the packet to be de-aliased.
-
-.Sh 6. Miscellaneous Functions
-
-.Ss 6.1 PacketAliasSetTarget()
-
-.Ft void
-.Fn PacketAliasSetTarget "struct in_addr addr"
-
-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 PacketAliasSetTarget().
-
-If this function is not called, or is called
-with a zero address argument, then all new
-incoming packets go to the address set by
-PacketAliasSetAddress.
-.Ss 6.2 PacketAliasCheckNewLink()
-
-.Ft int
-.Fn PacketAliasCheckNewLink "void"
-
-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 PacketAliasSetTarget()
-is called to change the default target address.
-.Ss 6.3 PacketAliasInternetChecksum()
-
-.Ft u_short
-.Fn PacketAliasInternetChecksum "u_short *buffer" "int nbytes"
-
-This is a utility function that does not seem
-to be available elswhere and is included as a
-convenience. It computes the internet checksum,
-which is used in both IP and protocol-specific
-headers (TCP, UDP, ICMP).
-
-.Em buffer
-points to the data block to be checksummed, and
-.Em nbytes
-is the number of bytes. The 16-bit checksum
-field should be zeroed before computing the checksum.
-
-Checksums can also be verified by operating on a block
-of data including its checksum. If the checksum is
-valid, PacketAliasInternetChecksum() will return zero.
-
-.Sh 7. Authors
-Charles Mott (cmott@srv.net), versions 1.0 - 1.8, 2.0 - 2.4.
-
-Eivind Eklund (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.
-
-.Sh 8. Acknowledgments
-
-Listed below, in approximate chronological
-order, are individuals who have provided
-valuable comments and/or debugging assistance.
-
-.Bl -inset -compact -offset left
-.It Gary Roberts
-.It Tom Torrance
-.It Reto Burkhalter
-.It Martin Renters
-.It Brian Somers
-.It Paul Traina
-.It Ari Suutari
-.It Dave Remien
-.It J. Fortes
-.It Andrzej Bialeki
-.It Gordon Burditt
-.El
-
-.Sh Appendix: Conceptual Background
-This appendix is intended for those who
-are planning to modify the source code or want
-to create somewhat esoteric applications using
-the packet aliasing functions.
-
-The conceptual framework under which the
-packet aliasing engine operates is described here.
-Central to the discussion is the idea of an
-"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 A.1 Aliasing Links
-There is a notion of an "aliasing link",
-which is 7-tuple describing a specific
-translation:
-.Bd -literal -offset indent
-(local addr, local port, alias addr, alias port,
- remote addr, remote port, protocol)
-.Ed
-
-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.
-
-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.)
-
-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 aliased IP address. In cases where
-conflicts might arise, the aliasing port
-is chosen so that uniqueness is maintained.
-.Ss A.2 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 A.3 Partially Specified Aliasing Links
-Aliasing links can be partially specified,
-meaning that the remote address and/or remote
-ports 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.
-
-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
-
-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 A.4 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
-
-Address mappings are searched when creating
-new dynamic links.
-
-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 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.
-
-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.
-
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
deleted file mode 100644
index 97d1983b0078..000000000000
--- a/sys/netinet/tcp_reass.c
+++ /dev/null
@@ -1,2231 +0,0 @@
-/*
- * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
- * The Regents of the University of California. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
- *
- * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
- * $Id: tcp_input.c,v 1.81 1998/09/11 16:04:03 wollman Exp $
- */
-
-#include "opt_ipfw.h" /* for ipfw_fwd */
-#include "opt_tcpdebug.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/proc.h> /* for proc0 declaration */
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/syslog.h>
-
-#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> /* for ICMP_BANDLIM */
-#include <netinet/in_pcb.h>
-#include <netinet/ip_var.h>
-#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
-#include <netinet/tcp.h>
-#include <netinet/tcp_fsm.h>
-#include <netinet/tcp_seq.h>
-#include <netinet/tcp_timer.h>
-#include <netinet/tcp_var.h>
-#include <netinet/tcpip.h>
-#ifdef TCPDEBUG
-#include <netinet/tcp_debug.h>
-static struct tcpiphdr tcp_saveti;
-#endif
-
-static int tcprexmtthresh = 3;
-tcp_seq tcp_iss;
-tcp_cc tcp_ccgen;
-
-struct tcpstat tcpstat;
-SYSCTL_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats,
- CTLFLAG_RD, &tcpstat , tcpstat, "");
-
-static int log_in_vain = 0;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW,
- &log_in_vain, 0, "");
-
-int tcp_delack_enabled = 1;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, delayed_ack, CTLFLAG_RW,
- &tcp_delack_enabled, 0, "");
-
-u_long tcp_now;
-struct inpcbhead tcb;
-struct inpcbinfo tcbinfo;
-
-static void tcp_dooptions __P((struct tcpcb *,
- u_char *, int, struct tcpiphdr *, struct tcpopt *));
-static void tcp_pulloutofband __P((struct socket *,
- struct tcpiphdr *, struct mbuf *));
-static int tcp_reass __P((struct tcpcb *, struct tcpiphdr *, struct mbuf *));
-static void tcp_xmit_timer __P((struct tcpcb *, int));
-
-
-/*
- * Insert segment ti into reassembly queue of tcp with
- * control block tp. Return TH_FIN if reassembly now includes
- * a segment with FIN. The macro form does the common case inline
- * (segment is the next to be received on an established connection,
- * and the queue is empty), avoiding linkage into and removal
- * from the queue and repetition of various conversions.
- * Set DELACK for segments received in order, but ack immediately
- * when segments are out of order (so fast retransmit can work).
- */
-#define TCP_REASS(tp, ti, m, so, flags) { \
- if ((ti)->ti_seq == (tp)->rcv_nxt && \
- (tp)->t_segq == NULL && \
- (tp)->t_state == TCPS_ESTABLISHED) { \
- if (tcp_delack_enabled) \
- tp->t_flags |= TF_DELACK; \
- else \
- tp->t_flags |= TF_ACKNOW; \
- (tp)->rcv_nxt += (ti)->ti_len; \
- flags = (ti)->ti_flags & TH_FIN; \
- tcpstat.tcps_rcvpack++;\
- tcpstat.tcps_rcvbyte += (ti)->ti_len;\
- sbappend(&(so)->so_rcv, (m)); \
- sorwakeup(so); \
- } else { \
- (flags) = tcp_reass((tp), (ti), (m)); \
- tp->t_flags |= TF_ACKNOW; \
- } \
-}
-
-static int
-tcp_reass(tp, ti, m)
- register struct tcpcb *tp;
- register struct tcpiphdr *ti;
- struct mbuf *m;
-{
- struct mbuf *q;
- struct mbuf *p;
- struct mbuf *nq;
- struct socket *so = tp->t_inpcb->inp_socket;
- int flags;
-
-#define GETTCP(m) ((struct tcpiphdr *)m->m_pkthdr.header)
-
- /*
- * Call with ti==0 after become established to
- * force pre-ESTABLISHED data up to user socket.
- */
- if (ti == 0)
- goto present;
-
- m->m_pkthdr.header = ti;
-
- /*
- * Find a segment which begins after this one does.
- */
- for (q = tp->t_segq, p = NULL; q; p = q, q = q->m_nextpkt)
- if (SEQ_GT(GETTCP(q)->ti_seq, ti->ti_seq))
- break;
-
- /*
- * If there is a preceding segment, it may provide some of
- * our data already. If so, drop the data from the incoming
- * segment. If it provides all of our data, drop us.
- */
- if (p != NULL) {
- register int i;
- /* conversion to int (in i) handles seq wraparound */
- i = GETTCP(p)->ti_seq + GETTCP(p)->ti_len - ti->ti_seq;
- if (i > 0) {
- if (i >= ti->ti_len) {
- tcpstat.tcps_rcvduppack++;
- tcpstat.tcps_rcvdupbyte += ti->ti_len;
- m_freem(m);
- /*
- * Try to present any queued data
- * at the left window edge to the user.
- * This is needed after the 3-WHS
- * completes.
- */
- goto present; /* ??? */
- }
- m_adj(m, i);
- ti->ti_len -= i;
- ti->ti_seq += i;
- }
- }
- tcpstat.tcps_rcvoopack++;
- tcpstat.tcps_rcvoobyte += ti->ti_len;
-
- /*
- * While we overlap succeeding segments trim them or,
- * if they are completely covered, dequeue them.
- */
- while (q) {
- register int i = (ti->ti_seq + ti->ti_len) - GETTCP(q)->ti_seq;
- if (i <= 0)
- break;
- if (i < GETTCP(q)->ti_len) {
- GETTCP(q)->ti_seq += i;
- GETTCP(q)->ti_len -= i;
- m_adj(q, i);
- break;
- }
-
- nq = q->m_nextpkt;
- if (p)
- p->m_nextpkt = nq;
- else
- tp->t_segq = nq;
- m_freem(q);
- q = nq;
- }
-
- if (p == NULL) {
- m->m_nextpkt = tp->t_segq;
- tp->t_segq = m;
- } else {
- m->m_nextpkt = p->m_nextpkt;
- p->m_nextpkt = m;
- }
-
-present:
- /*
- * Present data to user, advancing rcv_nxt through
- * completed sequence space.
- */
- if (!TCPS_HAVEESTABLISHED(tp->t_state))
- return (0);
- q = tp->t_segq;
- if (!q || GETTCP(q)->ti_seq != tp->rcv_nxt)
- return (0);
- do {
- tp->rcv_nxt += GETTCP(q)->ti_len;
- flags = GETTCP(q)->ti_flags & TH_FIN;
- nq = q->m_nextpkt;
- tp->t_segq = nq;
- q->m_nextpkt = NULL;
- if (so->so_state & SS_CANTRCVMORE)
- m_freem(q);
- else
- sbappend(&so->so_rcv, q);
- q = nq;
- } while (q && GETTCP(q)->ti_seq == tp->rcv_nxt);
- sorwakeup(so);
- return (flags);
-
-#undef GETTCP
-}
-
-/*
- * TCP input routine, follows pages 65-76 of the
- * protocol specification dated September, 1981 very closely.
- */
-void
-tcp_input(m, iphlen)
- register struct mbuf *m;
- int iphlen;
-{
- register struct tcpiphdr *ti;
- register struct inpcb *inp;
- u_char *optp = NULL;
- int optlen = 0;
- int len, tlen, off;
- register struct tcpcb *tp = 0;
- register int tiflags;
- struct socket *so = 0;
- int todrop, acked, ourfinisacked, needoutput = 0;
- struct in_addr laddr;
- int dropsocket = 0;
- int iss = 0;
- u_long tiwin;
- struct tcpopt to; /* options in this segment */
- struct rmxp_tao *taop; /* pointer to our TAO cache entry */
- struct rmxp_tao tao_noncached; /* in case there's no cached entry */
-#ifdef TCPDEBUG
- short ostate = 0;
-#endif
-
- bzero((char *)&to, sizeof(to));
-
- tcpstat.tcps_rcvtotal++;
- /*
- * Get IP and TCP header together in first mbuf.
- * Note: IP leaves IP header in first mbuf.
- */
- ti = mtod(m, struct tcpiphdr *);
- if (iphlen > sizeof (struct ip))
- ip_stripoptions(m, (struct mbuf *)0);
- if (m->m_len < sizeof (struct tcpiphdr)) {
- if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) {
- tcpstat.tcps_rcvshort++;
- return;
- }
- ti = mtod(m, struct tcpiphdr *);
- }
-
- /*
- * Checksum extended TCP header and data.
- */
- tlen = ((struct ip *)ti)->ip_len;
- len = sizeof (struct ip) + tlen;
- bzero(ti->ti_x1, sizeof(ti->ti_x1));
- ti->ti_len = (u_short)tlen;
- HTONS(ti->ti_len);
- ti->ti_sum = in_cksum(m, len);
- if (ti->ti_sum) {
- tcpstat.tcps_rcvbadsum++;
- goto drop;
- }
-
- /*
- * Check that TCP offset makes sense,
- * pull out TCP options and adjust length. XXX
- */
- off = ti->ti_off << 2;
- if (off < sizeof (struct tcphdr) || off > tlen) {
- tcpstat.tcps_rcvbadoff++;
- goto drop;
- }
- tlen -= off;
- ti->ti_len = tlen;
- if (off > sizeof (struct tcphdr)) {
- if (m->m_len < sizeof(struct ip) + off) {
- if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) {
- tcpstat.tcps_rcvshort++;
- return;
- }
- ti = mtod(m, struct tcpiphdr *);
- }
- optlen = off - sizeof (struct tcphdr);
- optp = mtod(m, u_char *) + sizeof (struct tcpiphdr);
- }
- tiflags = ti->ti_flags;
-
- /*
- * Convert TCP protocol specific fields to host format.
- */
- NTOHL(ti->ti_seq);
- NTOHL(ti->ti_ack);
- NTOHS(ti->ti_win);
- NTOHS(ti->ti_urp);
-
- /*
- * Drop TCP, IP headers and TCP options.
- */
- m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
- m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
-
- /*
- * Locate pcb for segment.
- */
-findpcb:
-#ifdef IPFIREWALL_FORWARD
- if (ip_fw_fwd_addr != NULL) {
- /*
- * Diverted. Pretend to be the destination.
- * already got one like this?
- */
- inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
- ti->ti_dst, ti->ti_dport, 0);
- if (!inp) {
- /*
- * No, then it's new. Try find the ambushing socket
- */
- if (!ip_fw_fwd_addr->sin_port) {
- inp = in_pcblookup_hash(&tcbinfo, ti->ti_src,
- ti->ti_sport, ip_fw_fwd_addr->sin_addr,
- ti->ti_dport, 1);
- } else {
- inp = in_pcblookup_hash(&tcbinfo,
- ti->ti_src, ti->ti_sport,
- ip_fw_fwd_addr->sin_addr,
- ntohs(ip_fw_fwd_addr->sin_port), 1);
- }
- }
- ip_fw_fwd_addr = NULL;
- } else
-#endif /* IPFIREWALL_FORWARD */
-
- inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
- ti->ti_dst, ti->ti_dport, 1);
-
- /*
- * If the state is CLOSED (i.e., TCB does not exist) then
- * all data in the incoming segment is discarded.
- * If the TCB exists but is in CLOSED state, it is embryonic,
- * but should either do a listen or a connect soon.
- */
- if (inp == NULL) {
- if (log_in_vain && tiflags & TH_SYN) {
- char buf[4*sizeof "123"];
-
- strcpy(buf, inet_ntoa(ti->ti_dst));
- log(LOG_INFO,
- "Connection attempt to TCP %s:%d from %s:%d\n",
- buf, ntohs(ti->ti_dport), inet_ntoa(ti->ti_src),
- ntohs(ti->ti_sport));
- }
-#ifdef ICMP_BANDLIM
- if (badport_bandlim(1) < 0)
- goto drop;
-#endif
- goto dropwithreset;
- }
- tp = intotcpcb(inp);
- if (tp == 0)
- goto dropwithreset;
- if (tp->t_state == TCPS_CLOSED)
- goto drop;
-
- /* Unscale the window into a 32-bit value. */
- if ((tiflags & TH_SYN) == 0)
- tiwin = ti->ti_win << tp->snd_scale;
- else
- tiwin = ti->ti_win;
-
- so = inp->inp_socket;
- if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
-#ifdef TCPDEBUG
- if (so->so_options & SO_DEBUG) {
- ostate = tp->t_state;
- tcp_saveti = *ti;
- }
-#endif
- if (so->so_options & SO_ACCEPTCONN) {
- register struct tcpcb *tp0 = tp;
- struct socket *so2;
- if ((tiflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {
- /*
- * Note: dropwithreset makes sure we don't
- * send a RST in response to a RST.
- */
- if (tiflags & TH_ACK) {
- tcpstat.tcps_badsyn++;
- goto dropwithreset;
- }
- goto drop;
- }
- so2 = sonewconn(so, 0);
- if (so2 == 0) {
- tcpstat.tcps_listendrop++;
- so2 = sodropablereq(so);
- if (so2) {
- tcp_drop(sototcpcb(so2), ETIMEDOUT);
- so2 = sonewconn(so, 0);
- }
- if (!so2)
- goto drop;
- }
- so = so2;
- /*
- * This is ugly, but ....
- *
- * Mark socket as temporary until we're
- * committed to keeping it. The code at
- * ``drop'' and ``dropwithreset'' check the
- * flag dropsocket to see if the temporary
- * socket created here should be discarded.
- * We mark the socket as discardable until
- * we're committed to it below in TCPS_LISTEN.
- */
- dropsocket++;
- inp = (struct inpcb *)so->so_pcb;
- inp->inp_laddr = ti->ti_dst;
- inp->inp_lport = ti->ti_dport;
- if (in_pcbinshash(inp) != 0) {
- /*
- * Undo the assignments above if we failed to put
- * the PCB on the hash lists.
- */
- inp->inp_laddr.s_addr = INADDR_ANY;
- inp->inp_lport = 0;
- goto drop;
- }
- inp->inp_options = ip_srcroute();
- tp = intotcpcb(inp);
- tp->t_state = TCPS_LISTEN;
- tp->t_flags |= tp0->t_flags & (TF_NOPUSH|TF_NOOPT);
-
- /* Compute proper scaling value from buffer space */
- while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
- TCP_MAXWIN << tp->request_r_scale < so->so_rcv.sb_hiwat)
- tp->request_r_scale++;
- }
- }
-
- /*
- * Segment received on connection.
- * Reset idle time and keep-alive timer.
- */
- tp->t_idle = 0;
- if (TCPS_HAVEESTABLISHED(tp->t_state))
- tp->t_timer[TCPT_KEEP] = tcp_keepidle;
-
- /*
- * Process options if not in LISTEN state,
- * else do it below (after getting remote address).
- */
- if (tp->t_state != TCPS_LISTEN)
- tcp_dooptions(tp, optp, optlen, ti, &to);
-
- /*
- * Header prediction: check for the two common cases
- * of a uni-directional data xfer. If the packet has
- * no control flags, is in-sequence, the window didn't
- * change and we're not retransmitting, it's a
- * candidate. If the length is zero and the ack moved
- * forward, we're the sender side of the xfer. Just
- * free the data acked & wake any higher level process
- * that was blocked waiting for space. If the length
- * is non-zero and the ack didn't move, we're the
- * receiver side. If we're getting packets in-order
- * (the reassembly queue is empty), add the data to
- * the socket buffer and note that we need a delayed ack.
- * Make sure that the hidden state-flags are also off.
- * Since we check for TCPS_ESTABLISHED above, it can only
- * be TH_NEEDSYN.
- */
- if (tp->t_state == TCPS_ESTABLISHED &&
- (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
- ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&
- ((to.to_flag & TOF_TS) == 0 ||
- TSTMP_GEQ(to.to_tsval, tp->ts_recent)) &&
- /*
- * Using the CC option is compulsory if once started:
- * the segment is OK if no T/TCP was negotiated or
- * if the segment has a CC option equal to CCrecv
- */
- ((tp->t_flags & (TF_REQ_CC|TF_RCVD_CC)) != (TF_REQ_CC|TF_RCVD_CC) ||
- (to.to_flag & TOF_CC) != 0 && to.to_cc == tp->cc_recv) &&
- ti->ti_seq == tp->rcv_nxt &&
- tiwin && tiwin == tp->snd_wnd &&
- tp->snd_nxt == tp->snd_max) {
-
- /*
- * If last ACK falls within this segment's sequence numbers,
- * record the timestamp.
- * NOTE that the test is modified according to the latest
- * proposal of the tcplw@cray.com list (Braden 1993/04/26).
- */
- if ((to.to_flag & TOF_TS) != 0 &&
- SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) {
- tp->ts_recent_age = tcp_now;
- tp->ts_recent = to.to_tsval;
- }
-
- if (ti->ti_len == 0) {
- if (SEQ_GT(ti->ti_ack, tp->snd_una) &&
- SEQ_LEQ(ti->ti_ack, tp->snd_max) &&
- tp->snd_cwnd >= tp->snd_wnd &&
- tp->t_dupacks < tcprexmtthresh) {
- /*
- * this is a pure ack for outstanding data.
- */
- ++tcpstat.tcps_predack;
- if ((to.to_flag & TOF_TS) != 0)
- tcp_xmit_timer(tp,
- tcp_now - to.to_tsecr + 1);
- else if (tp->t_rtt &&
- SEQ_GT(ti->ti_ack, tp->t_rtseq))
- tcp_xmit_timer(tp, tp->t_rtt);
- acked = ti->ti_ack - tp->snd_una;
- tcpstat.tcps_rcvackpack++;
- tcpstat.tcps_rcvackbyte += acked;
- sbdrop(&so->so_snd, acked);
- tp->snd_una = ti->ti_ack;
- m_freem(m);
-
- /*
- * If all outstanding data are acked, stop
- * retransmit timer, otherwise restart timer
- * using current (possibly backed-off) value.
- * If process is waiting for space,
- * wakeup/selwakeup/signal. If data
- * are ready to send, let tcp_output
- * decide between more output or persist.
- */
- if (tp->snd_una == tp->snd_max)
- tp->t_timer[TCPT_REXMT] = 0;
- else if (tp->t_timer[TCPT_PERSIST] == 0)
- tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
-
- sowwakeup(so);
- if (so->so_snd.sb_cc)
- (void) tcp_output(tp);
- return;
- }
- } else if (ti->ti_ack == tp->snd_una &&
- tp->t_segq == NULL &&
- ti->ti_len <= sbspace(&so->so_rcv)) {
- /*
- * this is a pure, in-sequence data packet
- * with nothing on the reassembly queue and
- * we have enough buffer space to take it.
- */
- ++tcpstat.tcps_preddat;
- tp->rcv_nxt += ti->ti_len;
- tcpstat.tcps_rcvpack++;
- tcpstat.tcps_rcvbyte += ti->ti_len;
- /*
- * Add data to socket buffer.
- */
- sbappend(&so->so_rcv, m);
- sorwakeup(so);
- if (tcp_delack_enabled) {
- tp->t_flags |= TF_DELACK;
- } else {
- tp->t_flags |= TF_ACKNOW;
- tcp_output(tp);
- }
- return;
- }
- }
-
- /*
- * Calculate amount of space in receive window,
- * and then do TCP input processing.
- * Receive window is amount of space in rcv queue,
- * but not less than advertised window.
- */
- { int win;
-
- win = sbspace(&so->so_rcv);
- if (win < 0)
- win = 0;
- tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt));
- }
-
- switch (tp->t_state) {
-
- /*
- * If the state is LISTEN then ignore segment if it contains an RST.
- * If the segment contains an ACK then it is bad and send a RST.
- * If it does not contain a SYN then it is not interesting; drop it.
- * If it is from this socket, drop it, it must be forged.
- * Don't bother responding if the destination was a broadcast.
- * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial
- * tp->iss, and send a segment:
- * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
- * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.
- * Fill in remote peer address fields if not previously specified.
- * Enter SYN_RECEIVED state, and process any other fields of this
- * segment in this state.
- */
- case TCPS_LISTEN: {
- register struct sockaddr_in *sin;
-
- if (tiflags & TH_RST)
- goto drop;
- if (tiflags & TH_ACK)
- goto dropwithreset;
- if ((tiflags & TH_SYN) == 0)
- goto drop;
- if ((ti->ti_dport == ti->ti_sport) &&
- (ti->ti_dst.s_addr == ti->ti_src.s_addr))
- goto drop;
- /*
- * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
- * in_broadcast() should never return true on a received
- * packet with M_BCAST not set.
- */
- if (m->m_flags & (M_BCAST|M_MCAST) ||
- IN_MULTICAST(ntohl(ti->ti_dst.s_addr)))
- goto drop;
- MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME,
- M_NOWAIT);
- if (sin == NULL)
- goto drop;
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(*sin);
- sin->sin_addr = ti->ti_src;
- sin->sin_port = ti->ti_sport;
- bzero((caddr_t)sin->sin_zero, sizeof(sin->sin_zero));
- laddr = inp->inp_laddr;
- if (inp->inp_laddr.s_addr == INADDR_ANY)
- inp->inp_laddr = ti->ti_dst;
- if (in_pcbconnect(inp, (struct sockaddr *)sin, &proc0)) {
- inp->inp_laddr = laddr;
- FREE(sin, M_SONAME);
- goto drop;
- }
- FREE(sin, M_SONAME);
- tp->t_template = tcp_template(tp);
- if (tp->t_template == 0) {
- tp = tcp_drop(tp, ENOBUFS);
- dropsocket = 0; /* socket is already gone */
- goto drop;
- }
- if ((taop = tcp_gettaocache(inp)) == NULL) {
- taop = &tao_noncached;
- bzero(taop, sizeof(*taop));
- }
- tcp_dooptions(tp, optp, optlen, ti, &to);
- if (iss)
- tp->iss = iss;
- else
- tp->iss = tcp_iss;
- tcp_iss += TCP_ISSINCR/4;
- tp->irs = ti->ti_seq;
- tcp_sendseqinit(tp);
- tcp_rcvseqinit(tp);
- /*
- * Initialization of the tcpcb for transaction;
- * set SND.WND = SEG.WND,
- * initialize CCsend and CCrecv.
- */
- tp->snd_wnd = tiwin; /* initial send-window */
- tp->cc_send = CC_INC(tcp_ccgen);
- tp->cc_recv = to.to_cc;
- /*
- * Perform TAO test on incoming CC (SEG.CC) option, if any.
- * - compare SEG.CC against cached CC from the same host,
- * if any.
- * - if SEG.CC > chached value, SYN must be new and is accepted
- * immediately: save new CC in the cache, mark the socket
- * connected, enter ESTABLISHED state, turn on flag to
- * send a SYN in the next segment.
- * A virtual advertised window is set in rcv_adv to
- * initialize SWS prevention. Then enter normal segment
- * processing: drop SYN, process data and FIN.
- * - otherwise do a normal 3-way handshake.
- */
- if ((to.to_flag & TOF_CC) != 0) {
- if (((tp->t_flags & TF_NOPUSH) != 0) &&
- taop->tao_cc != 0 && CC_GT(to.to_cc, taop->tao_cc)) {
-
- taop->tao_cc = to.to_cc;
- tp->t_state = TCPS_ESTABLISHED;
-
- /*
- * If there is a FIN, or if there is data and the
- * connection is local, then delay SYN,ACK(SYN) in
- * the hope of piggy-backing it on a response
- * segment. Otherwise must send ACK now in case
- * the other side is slow starting.
- */
- if (tcp_delack_enabled && ((tiflags & TH_FIN) || (ti->ti_len != 0 &&
- in_localaddr(inp->inp_faddr))))
- tp->t_flags |= (TF_DELACK | TF_NEEDSYN);
- else
- tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN);
-
- /*
- * Limit the `virtual advertised window' to TCP_MAXWIN
- * here. Even if we requested window scaling, it will
- * become effective only later when our SYN is acked.
- */
- tp->rcv_adv += min(tp->rcv_wnd, TCP_MAXWIN);
- tcpstat.tcps_connects++;
- soisconnected(so);
- tp->t_timer[TCPT_KEEP] = tcp_keepinit;
- dropsocket = 0; /* committed to socket */
- tcpstat.tcps_accepts++;
- goto trimthenstep6;
- }
- /* else do standard 3-way handshake */
- } else {
- /*
- * No CC option, but maybe CC.NEW:
- * invalidate cached value.
- */
- taop->tao_cc = 0;
- }
- /*
- * TAO test failed or there was no CC option,
- * do a standard 3-way handshake.
- */
- tp->t_flags |= TF_ACKNOW;
- tp->t_state = TCPS_SYN_RECEIVED;
- tp->t_timer[TCPT_KEEP] = tcp_keepinit;
- dropsocket = 0; /* committed to socket */
- tcpstat.tcps_accepts++;
- goto trimthenstep6;
- }
-
- /*
- * If the state is SYN_RECEIVED:
- * if seg contains an ACK, but not for our SYN/ACK, send a RST.
- */
- case TCPS_SYN_RECEIVED:
- if ((tiflags & TH_ACK) &&
- (SEQ_LEQ(ti->ti_ack, tp->snd_una) ||
- SEQ_GT(ti->ti_ack, tp->snd_max)))
- goto dropwithreset;
- break;
-
- /*
- * If the state is SYN_SENT:
- * if seg contains an ACK, but not for our SYN, drop the input.
- * if seg contains a RST, then drop the connection.
- * if seg does not contain SYN, then drop it.
- * Otherwise this is an acceptable SYN segment
- * initialize tp->rcv_nxt and tp->irs
- * if seg contains ack then advance tp->snd_una
- * if SYN has been acked change to ESTABLISHED else SYN_RCVD state
- * arrange for segment to be acked (eventually)
- * continue processing rest of data/controls, beginning with URG
- */
- case TCPS_SYN_SENT:
- if ((taop = tcp_gettaocache(inp)) == NULL) {
- taop = &tao_noncached;
- bzero(taop, sizeof(*taop));
- }
-
- if ((tiflags & TH_ACK) &&
- (SEQ_LEQ(ti->ti_ack, tp->iss) ||
- SEQ_GT(ti->ti_ack, tp->snd_max))) {
- /*
- * If we have a cached CCsent for the remote host,
- * hence we haven't just crashed and restarted,
- * do not send a RST. This may be a retransmission
- * from the other side after our earlier ACK was lost.
- * Our new SYN, when it arrives, will serve as the
- * needed ACK.
- */
- if (taop->tao_ccsent != 0)
- goto drop;
- else
- goto dropwithreset;
- }
- if (tiflags & TH_RST) {
- if (tiflags & TH_ACK)
- tp = tcp_drop(tp, ECONNREFUSED);
- goto drop;
- }
- if ((tiflags & TH_SYN) == 0)
- goto drop;
- tp->snd_wnd = ti->ti_win; /* initial send window */
- tp->cc_recv = to.to_cc; /* foreign CC */
-
- tp->irs = ti->ti_seq;
- tcp_rcvseqinit(tp);
- if (tiflags & TH_ACK) {
- /*
- * Our SYN was acked. If segment contains CC.ECHO
- * option, check it to make sure this segment really
- * matches our SYN. If not, just drop it as old
- * duplicate, but send an RST if we're still playing
- * by the old rules. If no CC.ECHO option, make sure
- * we don't get fooled into using T/TCP.
- */
- if (to.to_flag & TOF_CCECHO) {
- if (tp->cc_send != to.to_ccecho)
- if (taop->tao_ccsent != 0)
- goto drop;
- else
- goto dropwithreset;
- } else
- tp->t_flags &= ~TF_RCVD_CC;
- tcpstat.tcps_connects++;
- soisconnected(so);
- /* Do window scaling on this connection? */
- if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
- (TF_RCVD_SCALE|TF_REQ_SCALE)) {
- tp->snd_scale = tp->requested_s_scale;
- tp->rcv_scale = tp->request_r_scale;
- }
- /* Segment is acceptable, update cache if undefined. */
- if (taop->tao_ccsent == 0)
- taop->tao_ccsent = to.to_ccecho;
-
- tp->rcv_adv += tp->rcv_wnd;
- tp->snd_una++; /* SYN is acked */
- /*
- * If there's data, delay ACK; if there's also a FIN
- * ACKNOW will be turned on later.
- */
- if (tcp_delack_enabled && ti->ti_len != 0)
- tp->t_flags |= TF_DELACK;
- else
- tp->t_flags |= TF_ACKNOW;
- /*
- * Received <SYN,ACK> in SYN_SENT[*] state.
- * Transitions:
- * SYN_SENT --> ESTABLISHED
- * SYN_SENT* --> FIN_WAIT_1
- */
- if (tp->t_flags & TF_NEEDFIN) {
- tp->t_state = TCPS_FIN_WAIT_1;
- tp->t_flags &= ~TF_NEEDFIN;
- tiflags &= ~TH_SYN;
- } else {
- tp->t_state = TCPS_ESTABLISHED;
- tp->t_timer[TCPT_KEEP] = tcp_keepidle;
- }
- } else {
- /*
- * Received initial SYN in SYN-SENT[*] state => simul-
- * taneous open. If segment contains CC option and there is
- * a cached CC, apply TAO test; if it succeeds, connection is
- * half-synchronized. Otherwise, do 3-way handshake:
- * SYN-SENT -> SYN-RECEIVED
- * SYN-SENT* -> SYN-RECEIVED*
- * If there was no CC option, clear cached CC value.
- */
- tp->t_flags |= TF_ACKNOW;
- tp->t_timer[TCPT_REXMT] = 0;
- if (to.to_flag & TOF_CC) {
- if (taop->tao_cc != 0 &&
- CC_GT(to.to_cc, taop->tao_cc)) {
- /*
- * update cache and make transition:
- * SYN-SENT -> ESTABLISHED*
- * SYN-SENT* -> FIN-WAIT-1*
- */
- taop->tao_cc = to.to_cc;
- if (tp->t_flags & TF_NEEDFIN) {
- tp->t_state = TCPS_FIN_WAIT_1;
- tp->t_flags &= ~TF_NEEDFIN;
- } else {
- tp->t_state = TCPS_ESTABLISHED;
- tp->t_timer[TCPT_KEEP] = tcp_keepidle;
- }
- tp->t_flags |= TF_NEEDSYN;
- } else
- tp->t_state = TCPS_SYN_RECEIVED;
- } else {
- /* CC.NEW or no option => invalidate cache */
- taop->tao_cc = 0;
- tp->t_state = TCPS_SYN_RECEIVED;
- }
- }
-
-trimthenstep6:
- /*
- * Advance ti->ti_seq to correspond to first data byte.
- * If data, trim to stay within window,
- * dropping FIN if necessary.
- */
- ti->ti_seq++;
- if (ti->ti_len > tp->rcv_wnd) {
- todrop = ti->ti_len - tp->rcv_wnd;
- m_adj(m, -todrop);
- ti->ti_len = tp->rcv_wnd;
- tiflags &= ~TH_FIN;
- tcpstat.tcps_rcvpackafterwin++;
- tcpstat.tcps_rcvbyteafterwin += todrop;
- }
- tp->snd_wl1 = ti->ti_seq - 1;
- tp->rcv_up = ti->ti_seq;
- /*
- * Client side of transaction: already sent SYN and data.
- * If the remote host used T/TCP to validate the SYN,
- * our data will be ACK'd; if so, enter normal data segment
- * processing in the middle of step 5, ack processing.
- * Otherwise, goto step 6.
- */
- if (tiflags & TH_ACK)
- goto process_ACK;
- goto step6;
- /*
- * If the state is LAST_ACK or CLOSING or TIME_WAIT:
- * if segment contains a SYN and CC [not CC.NEW] option:
- * if state == TIME_WAIT and connection duration > MSL,
- * drop packet and send RST;
- *
- * if SEG.CC > CCrecv then is new SYN, and can implicitly
- * ack the FIN (and data) in retransmission queue.
- * Complete close and delete TCPCB. Then reprocess
- * segment, hoping to find new TCPCB in LISTEN state;
- *
- * else must be old SYN; drop it.
- * else do normal processing.
- */
- case TCPS_LAST_ACK:
- case TCPS_CLOSING:
- case TCPS_TIME_WAIT:
- if ((tiflags & TH_SYN) &&
- (to.to_flag & TOF_CC) && tp->cc_recv != 0) {
- if (tp->t_state == TCPS_TIME_WAIT &&
- tp->t_duration > TCPTV_MSL)
- goto dropwithreset;
- if (CC_GT(to.to_cc, tp->cc_recv)) {
- tp = tcp_close(tp);
- goto findpcb;
- }
- else
- goto drop;
- }
- break; /* continue normal processing */
- }
-
- /*
- * States other than LISTEN or SYN_SENT.
- * First check the RST flag and sequence number since reset segments
- * are exempt from the timestamp and connection count tests. This
- * fixes a bug introduced by the Stevens, vol. 2, p. 960 bugfix
- * below which allowed reset segments in half the sequence space
- * to fall though and be processed (which gives forged reset
- * segments with a random sequence number a 50 percent chance of
- * killing a connection).
- * Then check timestamp, if present.
- * Then check the connection count, if present.
- * Then check that at least some bytes of segment are within
- * receive window. If segment begins before rcv_nxt,
- * drop leading data (and SYN); if nothing left, just ack.
- *
- *
- * If the RST bit is set, check the sequence number to see
- * if this is a valid reset segment.
- * RFC 793 page 37:
- * In all states except SYN-SENT, all reset (RST) segments
- * are validated by checking their SEQ-fields. A reset is
- * valid if its sequence number is in the window.
- * Note: this does not take into account delayed ACKs, so
- * we should test against last_ack_sent instead of rcv_nxt.
- * Also, it does not make sense to allow reset segments with
- * sequence numbers greater than last_ack_sent to be processed
- * since these sequence numbers are just the acknowledgement
- * numbers in our outgoing packets being echoed back at us,
- * and these acknowledgement numbers are monotonically
- * increasing.
- * If we have multiple segments in flight, the intial reset
- * segment sequence numbers will be to the left of last_ack_sent,
- * but they will eventually catch up.
- * In any case, it never made sense to trim reset segments to
- * fit the receive window since RFC 1122 says:
- * 4.2.2.12 RST Segment: RFC-793 Section 3.4
- *
- * A TCP SHOULD allow a received RST segment to include data.
- *
- * DISCUSSION
- * It has been suggested that a RST segment could contain
- * ASCII text that encoded and explained the cause of the
- * RST. No standard has yet been established for such
- * data.
- *
- * If the reset segment passes the sequence number test examine
- * the state:
- * SYN_RECEIVED STATE:
- * If passive open, return to LISTEN state.
- * If active open, inform user that connection was refused.
- * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
- * Inform user that connection was reset, and close tcb.
- * CLOSING, LAST_ACK, TIME_WAIT STATES
- * Close the tcb.
- * TIME_WAIT state:
- * Drop the segment - see Stevens, vol. 2, p. 964 and
- * RFC 1337.
- */
- if (tiflags & TH_RST) {
- if (tp->last_ack_sent == ti->ti_seq) {
- switch (tp->t_state) {
-
- case TCPS_SYN_RECEIVED:
- so->so_error = ECONNREFUSED;
- goto close;
-
- case TCPS_ESTABLISHED:
- case TCPS_FIN_WAIT_1:
- case TCPS_FIN_WAIT_2:
- case TCPS_CLOSE_WAIT:
- so->so_error = ECONNRESET;
- close:
- tp->t_state = TCPS_CLOSED;
- tcpstat.tcps_drops++;
- tp = tcp_close(tp);
- break;
-
- case TCPS_CLOSING:
- case TCPS_LAST_ACK:
- tp = tcp_close(tp);
- break;
-
- case TCPS_TIME_WAIT:
- break;
- }
- }
- goto drop;
- }
-
- /*
- * RFC 1323 PAWS: If we have a timestamp reply on this segment
- * and it's less than ts_recent, drop it.
- */
- if ((to.to_flag & TOF_TS) != 0 && tp->ts_recent &&
- TSTMP_LT(to.to_tsval, tp->ts_recent)) {
-
- /* Check to see if ts_recent is over 24 days old. */
- if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {
- /*
- * Invalidate ts_recent. If this segment updates
- * ts_recent, the age will be reset later and ts_recent
- * will get a valid value. If it does not, setting
- * ts_recent to zero will at least satisfy the
- * requirement that zero be placed in the timestamp
- * echo reply when ts_recent isn't valid. The
- * age isn't reset until we get a valid ts_recent
- * because we don't want out-of-order segments to be
- * dropped when ts_recent is old.
- */
- tp->ts_recent = 0;
- } else {
- tcpstat.tcps_rcvduppack++;
- tcpstat.tcps_rcvdupbyte += ti->ti_len;
- tcpstat.tcps_pawsdrop++;
- goto dropafterack;
- }
- }
-
- /*
- * T/TCP mechanism
- * If T/TCP was negotiated and the segment doesn't have CC,
- * or if its CC is wrong then drop the segment.
- * RST segments do not have to comply with this.
- */
- if ((tp->t_flags & (TF_REQ_CC|TF_RCVD_CC)) == (TF_REQ_CC|TF_RCVD_CC) &&
- ((to.to_flag & TOF_CC) == 0 || tp->cc_recv != to.to_cc))
- goto dropafterack;
-
- /*
- * In the SYN-RECEIVED state, validate that the packet belongs to
- * this connection before trimming the data to fit the receive
- * window. Check the sequence number versus IRS since we know
- * the sequence numbers haven't wrapped. This is a partial fix
- * for the "LAND" DoS attack.
- */
- if (tp->t_state == TCPS_SYN_RECEIVED && SEQ_LT(ti->ti_seq, tp->irs))
- goto dropwithreset;
-
- todrop = tp->rcv_nxt - ti->ti_seq;
- if (todrop > 0) {
- if (tiflags & TH_SYN) {
- tiflags &= ~TH_SYN;
- ti->ti_seq++;
- if (ti->ti_urp > 1)
- ti->ti_urp--;
- else
- tiflags &= ~TH_URG;
- todrop--;
- }
- /*
- * Following if statement from Stevens, vol. 2, p. 960.
- */
- if (todrop > ti->ti_len
- || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) {
- /*
- * Any valid FIN must be to the left of the window.
- * At this point the FIN must be a duplicate or out
- * of sequence; drop it.
- */
- tiflags &= ~TH_FIN;
-
- /*
- * Send an ACK to resynchronize and drop any data.
- * But keep on processing for RST or ACK.
- */
- tp->t_flags |= TF_ACKNOW;
- todrop = ti->ti_len;
- tcpstat.tcps_rcvduppack++;
- tcpstat.tcps_rcvdupbyte += todrop;
- } else {
- tcpstat.tcps_rcvpartduppack++;
- tcpstat.tcps_rcvpartdupbyte += todrop;
- }
- m_adj(m, todrop);
- ti->ti_seq += todrop;
- ti->ti_len -= todrop;
- if (ti->ti_urp > todrop)
- ti->ti_urp -= todrop;
- else {
- tiflags &= ~TH_URG;
- ti->ti_urp = 0;
- }
- }
-
- /*
- * If new data are received on a connection after the
- * user processes are gone, then RST the other end.
- */
- if ((so->so_state & SS_NOFDREF) &&
- tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
- tp = tcp_close(tp);
- tcpstat.tcps_rcvafterclose++;
- goto dropwithreset;
- }
-
- /*
- * If segment ends after window, drop trailing data
- * (and PUSH and FIN); if nothing left, just ACK.
- */
- todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
- if (todrop > 0) {
- tcpstat.tcps_rcvpackafterwin++;
- if (todrop >= ti->ti_len) {
- tcpstat.tcps_rcvbyteafterwin += ti->ti_len;
- /*
- * If a new connection request is received
- * while in TIME_WAIT, drop the old connection
- * and start over if the sequence numbers
- * are above the previous ones.
- */
- if (tiflags & TH_SYN &&
- tp->t_state == TCPS_TIME_WAIT &&
- SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
- iss = tp->rcv_nxt + TCP_ISSINCR;
- tp = tcp_close(tp);
- goto findpcb;
- }
- /*
- * If window is closed can only take segments at
- * window edge, and have to drop data and PUSH from
- * incoming segments. Continue processing, but
- * remember to ack. Otherwise, drop segment
- * and ack.
- */
- if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
- tp->t_flags |= TF_ACKNOW;
- tcpstat.tcps_rcvwinprobe++;
- } else
- goto dropafterack;
- } else
- tcpstat.tcps_rcvbyteafterwin += todrop;
- m_adj(m, -todrop);
- ti->ti_len -= todrop;
- tiflags &= ~(TH_PUSH|TH_FIN);
- }
-
- /*
- * If last ACK falls within this segment's sequence numbers,
- * record its timestamp.
- * NOTE that the test is modified according to the latest
- * proposal of the tcplw@cray.com list (Braden 1993/04/26).
- */
- if ((to.to_flag & TOF_TS) != 0 &&
- SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) {
- tp->ts_recent_age = tcp_now;
- tp->ts_recent = to.to_tsval;
- }
-
- /*
- * If a SYN is in the window, then this is an
- * error and we send an RST and drop the connection.
- */
- if (tiflags & TH_SYN) {
- tp = tcp_drop(tp, ECONNRESET);
- goto dropwithreset;
- }
-
- /*
- * If the ACK bit is off: if in SYN-RECEIVED state or SENDSYN
- * flag is on (half-synchronized state), then queue data for
- * later processing; else drop segment and return.
- */
- if ((tiflags & TH_ACK) == 0) {
- if (tp->t_state == TCPS_SYN_RECEIVED ||
- (tp->t_flags & TF_NEEDSYN))
- goto step6;
- else
- goto drop;
- }
-
- /*
- * Ack processing.
- */
- switch (tp->t_state) {
-
- /*
- * In SYN_RECEIVED state, the ack ACKs our SYN, so enter
- * ESTABLISHED state and continue processing.
- * The ACK was checked above.
- */
- case TCPS_SYN_RECEIVED:
-
- tcpstat.tcps_connects++;
- soisconnected(so);
- /* Do window scaling? */
- if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
- (TF_RCVD_SCALE|TF_REQ_SCALE)) {
- tp->snd_scale = tp->requested_s_scale;
- tp->rcv_scale = tp->request_r_scale;
- }
- /*
- * Upon successful completion of 3-way handshake,
- * update cache.CC if it was undefined, pass any queued
- * data to the user, and advance state appropriately.
- */
- if ((taop = tcp_gettaocache(inp)) != NULL &&
- taop->tao_cc == 0)
- taop->tao_cc = tp->cc_recv;
-
- /*
- * Make transitions:
- * SYN-RECEIVED -> ESTABLISHED
- * SYN-RECEIVED* -> FIN-WAIT-1
- */
- if (tp->t_flags & TF_NEEDFIN) {
- tp->t_state = TCPS_FIN_WAIT_1;
- tp->t_flags &= ~TF_NEEDFIN;
- } else {
- tp->t_state = TCPS_ESTABLISHED;
- tp->t_timer[TCPT_KEEP] = tcp_keepidle;
- }
- /*
- * If segment contains data or ACK, will call tcp_reass()
- * later; if not, do so now to pass queued data to user.
- */
- if (ti->ti_len == 0 && (tiflags & TH_FIN) == 0)
- (void) tcp_reass(tp, (struct tcpiphdr *)0,
- (struct mbuf *)0);
- tp->snd_wl1 = ti->ti_seq - 1;
- /* fall into ... */
-
- /*
- * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
- * ACKs. If the ack is in the range
- * tp->snd_una < ti->ti_ack <= tp->snd_max
- * then advance tp->snd_una to ti->ti_ack and drop
- * data from the retransmission queue. If this ACK reflects
- * more up to date window information we update our window information.
- */
- case TCPS_ESTABLISHED:
- case TCPS_FIN_WAIT_1:
- case TCPS_FIN_WAIT_2:
- case TCPS_CLOSE_WAIT:
- case TCPS_CLOSING:
- case TCPS_LAST_ACK:
- case TCPS_TIME_WAIT:
-
- if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
- if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
- tcpstat.tcps_rcvdupack++;
- /*
- * If we have outstanding data (other than
- * a window probe), this is a completely
- * duplicate ack (ie, window info didn't
- * change), the ack is the biggest we've
- * seen and we've seen exactly our rexmt
- * threshhold of them, assume a packet
- * has been dropped and retransmit it.
- * Kludge snd_nxt & the congestion
- * window so we send only this one
- * packet.
- *
- * We know we're losing at the current
- * window size so do congestion avoidance
- * (set ssthresh to half the current window
- * and pull our congestion window back to
- * the new ssthresh).
- *
- * Dup acks mean that packets have left the
- * network (they're now cached at the receiver)
- * so bump cwnd by the amount in the receiver
- * to keep a constant cwnd packets in the
- * network.
- */
- if (tp->t_timer[TCPT_REXMT] == 0 ||
- ti->ti_ack != tp->snd_una)
- tp->t_dupacks = 0;
- else if (++tp->t_dupacks == tcprexmtthresh) {
- tcp_seq onxt = tp->snd_nxt;
- u_int win =
- min(tp->snd_wnd, tp->snd_cwnd) / 2 /
- tp->t_maxseg;
-
- if (win < 2)
- win = 2;
- tp->snd_ssthresh = win * tp->t_maxseg;
- tp->t_timer[TCPT_REXMT] = 0;
- tp->t_rtt = 0;
- tp->snd_nxt = ti->ti_ack;
- tp->snd_cwnd = tp->t_maxseg;
- (void) tcp_output(tp);
- tp->snd_cwnd = tp->snd_ssthresh +
- tp->t_maxseg * tp->t_dupacks;
- if (SEQ_GT(onxt, tp->snd_nxt))
- tp->snd_nxt = onxt;
- goto drop;
- } else if (tp->t_dupacks > tcprexmtthresh) {
- tp->snd_cwnd += tp->t_maxseg;
- (void) tcp_output(tp);
- goto drop;
- }
- } else
- tp->t_dupacks = 0;
- break;
- }
- /*
- * If the congestion window was inflated to account
- * for the other side's cached packets, retract it.
- */
- if (tp->t_dupacks >= tcprexmtthresh &&
- tp->snd_cwnd > tp->snd_ssthresh)
- tp->snd_cwnd = tp->snd_ssthresh;
- tp->t_dupacks = 0;
- if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
- tcpstat.tcps_rcvacktoomuch++;
- goto dropafterack;
- }
- /*
- * If we reach this point, ACK is not a duplicate,
- * i.e., it ACKs something we sent.
- */
- if (tp->t_flags & TF_NEEDSYN) {
- /*
- * T/TCP: Connection was half-synchronized, and our
- * SYN has been ACK'd (so connection is now fully
- * synchronized). Go to non-starred state,
- * increment snd_una for ACK of SYN, and check if
- * we can do window scaling.
- */
- tp->t_flags &= ~TF_NEEDSYN;
- tp->snd_una++;
- /* Do window scaling? */
- if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
- (TF_RCVD_SCALE|TF_REQ_SCALE)) {
- tp->snd_scale = tp->requested_s_scale;
- tp->rcv_scale = tp->request_r_scale;
- }
- }
-
-process_ACK:
- acked = ti->ti_ack - tp->snd_una;
- tcpstat.tcps_rcvackpack++;
- tcpstat.tcps_rcvackbyte += acked;
-
- /*
- * If we have a timestamp reply, update smoothed
- * round trip time. If no timestamp is present but
- * transmit timer is running and timed sequence
- * number was acked, update smoothed round trip time.
- * Since we now have an rtt measurement, cancel the
- * timer backoff (cf., Phil Karn's retransmit alg.).
- * Recompute the initial retransmit timer.
- */
- if (to.to_flag & TOF_TS)
- tcp_xmit_timer(tp, tcp_now - to.to_tsecr + 1);
- else if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
- tcp_xmit_timer(tp,tp->t_rtt);
-
- /*
- * If all outstanding data is acked, stop retransmit
- * timer and remember to restart (more output or persist).
- * If there is more data to be acked, restart retransmit
- * timer, using current (possibly backed-off) value.
- */
- if (ti->ti_ack == tp->snd_max) {
- tp->t_timer[TCPT_REXMT] = 0;
- needoutput = 1;
- } else if (tp->t_timer[TCPT_PERSIST] == 0)
- tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
-
- /*
- * If no data (only SYN) was ACK'd,
- * skip rest of ACK processing.
- */
- if (acked == 0)
- goto step6;
-
- /*
- * When new data is acked, open the congestion window.
- * If the window gives us less than ssthresh packets
- * in flight, open exponentially (maxseg per packet).
- * Otherwise open linearly: maxseg per window
- * (maxseg^2 / cwnd per packet).
- */
- {
- register u_int cw = tp->snd_cwnd;
- register u_int incr = tp->t_maxseg;
-
- if (cw > tp->snd_ssthresh)
- incr = incr * incr / cw;
- tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);
- }
- if (acked > so->so_snd.sb_cc) {
- tp->snd_wnd -= so->so_snd.sb_cc;
- sbdrop(&so->so_snd, (int)so->so_snd.sb_cc);
- ourfinisacked = 1;
- } else {
- sbdrop(&so->so_snd, acked);
- tp->snd_wnd -= acked;
- ourfinisacked = 0;
- }
- sowwakeup(so);
- tp->snd_una = ti->ti_ack;
- if (SEQ_LT(tp->snd_nxt, tp->snd_una))
- tp->snd_nxt = tp->snd_una;
-
- switch (tp->t_state) {
-
- /*
- * In FIN_WAIT_1 STATE in addition to the processing
- * for the ESTABLISHED state if our FIN is now acknowledged
- * then enter FIN_WAIT_2.
- */
- case TCPS_FIN_WAIT_1:
- if (ourfinisacked) {
- /*
- * If we can't receive any more
- * data, then closing user can proceed.
- * Starting the timer is contrary to the
- * specification, but if we don't get a FIN
- * we'll hang forever.
- */
- if (so->so_state & SS_CANTRCVMORE) {
- soisdisconnected(so);
- tp->t_timer[TCPT_2MSL] = tcp_maxidle;
- }
- tp->t_state = TCPS_FIN_WAIT_2;
- }
- break;
-
- /*
- * In CLOSING STATE in addition to the processing for
- * the ESTABLISHED state if the ACK acknowledges our FIN
- * then enter the TIME-WAIT state, otherwise ignore
- * the segment.
- */
- case TCPS_CLOSING:
- if (ourfinisacked) {
- tp->t_state = TCPS_TIME_WAIT;
- tcp_canceltimers(tp);
- /* Shorten TIME_WAIT [RFC-1644, p.28] */
- if (tp->cc_recv != 0 &&
- tp->t_duration < TCPTV_MSL)
- tp->t_timer[TCPT_2MSL] =
- tp->t_rxtcur * TCPTV_TWTRUNC;
- else
- tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
- soisdisconnected(so);
- }
- break;
-
- /*
- * In LAST_ACK, we may still be waiting for data to drain
- * and/or to be acked, as well as for the ack of our FIN.
- * If our FIN is now acknowledged, delete the TCB,
- * enter the closed state and return.
- */
- case TCPS_LAST_ACK:
- if (ourfinisacked) {
- tp = tcp_close(tp);
- goto drop;
- }
- break;
-
- /*
- * In TIME_WAIT state the only thing that should arrive
- * is a retransmission of the remote FIN. Acknowledge
- * it and restart the finack timer.
- */
- case TCPS_TIME_WAIT:
- tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
- goto dropafterack;
- }
- }
-
-step6:
- /*
- * Update window information.
- * Don't look at window if no ACK: TAC's send garbage on first SYN.
- */
- if ((tiflags & TH_ACK) &&
- (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
- (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
- (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
- /* keep track of pure window updates */
- if (ti->ti_len == 0 &&
- tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
- tcpstat.tcps_rcvwinupd++;
- tp->snd_wnd = tiwin;
- tp->snd_wl1 = ti->ti_seq;
- tp->snd_wl2 = ti->ti_ack;
- if (tp->snd_wnd > tp->max_sndwnd)
- tp->max_sndwnd = tp->snd_wnd;
- needoutput = 1;
- }
-
- /*
- * Process segments with URG.
- */
- if ((tiflags & TH_URG) && ti->ti_urp &&
- TCPS_HAVERCVDFIN(tp->t_state) == 0) {
- /*
- * This is a kludge, but if we receive and accept
- * random urgent pointers, we'll crash in
- * soreceive. It's hard to imagine someone
- * actually wanting to send this much urgent data.
- */
- if (ti->ti_urp + so->so_rcv.sb_cc > sb_max) {
- ti->ti_urp = 0; /* XXX */
- tiflags &= ~TH_URG; /* XXX */
- goto dodata; /* XXX */
- }
- /*
- * If this segment advances the known urgent pointer,
- * then mark the data stream. This should not happen
- * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
- * a FIN has been received from the remote side.
- * In these states we ignore the URG.
- *
- * According to RFC961 (Assigned Protocols),
- * the urgent pointer points to the last octet
- * of urgent data. We continue, however,
- * to consider it to indicate the first octet
- * of data past the urgent section as the original
- * spec states (in one of two places).
- */
- if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
- tp->rcv_up = ti->ti_seq + ti->ti_urp;
- so->so_oobmark = so->so_rcv.sb_cc +
- (tp->rcv_up - tp->rcv_nxt) - 1;
- if (so->so_oobmark == 0)
- so->so_state |= SS_RCVATMARK;
- sohasoutofband(so);
- tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
- }
- /*
- * Remove out of band data so doesn't get presented to user.
- * This can happen independent of advancing the URG pointer,
- * but if two URG's are pending at once, some out-of-band
- * data may creep in... ick.
- */
- if (ti->ti_urp <= (u_long)ti->ti_len
-#ifdef SO_OOBINLINE
- && (so->so_options & SO_OOBINLINE) == 0
-#endif
- )
- tcp_pulloutofband(so, ti, m);
- } else
- /*
- * If no out of band data is expected,
- * pull receive urgent pointer along
- * with the receive window.
- */
- if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
- tp->rcv_up = tp->rcv_nxt;
-dodata: /* XXX */
-
- /*
- * Process the segment text, merging it into the TCP sequencing queue,
- * and arranging for acknowledgment of receipt if necessary.
- * This process logically involves adjusting tp->rcv_wnd as data
- * is presented to the user (this happens in tcp_usrreq.c,
- * case PRU_RCVD). If a FIN has already been received on this
- * connection then we just ignore the text.
- */
- if ((ti->ti_len || (tiflags&TH_FIN)) &&
- TCPS_HAVERCVDFIN(tp->t_state) == 0) {
- TCP_REASS(tp, ti, m, so, tiflags);
- /*
- * Note the amount of data that peer has sent into
- * our window, in order to estimate the sender's
- * buffer size.
- */
- len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt);
- } else {
- m_freem(m);
- tiflags &= ~TH_FIN;
- }
-
- /*
- * If FIN is received ACK the FIN and let the user know
- * that the connection is closing.
- */
- if (tiflags & TH_FIN) {
- if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
- socantrcvmore(so);
- /*
- * If connection is half-synchronized
- * (ie NEEDSYN flag on) then delay ACK,
- * so it may be piggybacked when SYN is sent.
- * Otherwise, since we received a FIN then no
- * more input can be expected, send ACK now.
- */
- if (tcp_delack_enabled && (tp->t_flags & TF_NEEDSYN))
- tp->t_flags |= TF_DELACK;
- else
- tp->t_flags |= TF_ACKNOW;
- tp->rcv_nxt++;
- }
- switch (tp->t_state) {
-
- /*
- * In SYN_RECEIVED and ESTABLISHED STATES
- * enter the CLOSE_WAIT state.
- */
- case TCPS_SYN_RECEIVED:
- case TCPS_ESTABLISHED:
- tp->t_state = TCPS_CLOSE_WAIT;
- break;
-
- /*
- * If still in FIN_WAIT_1 STATE FIN has not been acked so
- * enter the CLOSING state.
- */
- case TCPS_FIN_WAIT_1:
- tp->t_state = TCPS_CLOSING;
- break;
-
- /*
- * In FIN_WAIT_2 state enter the TIME_WAIT state,
- * starting the time-wait timer, turning off the other
- * standard timers.
- */
- case TCPS_FIN_WAIT_2:
- tp->t_state = TCPS_TIME_WAIT;
- tcp_canceltimers(tp);
- /* Shorten TIME_WAIT [RFC-1644, p.28] */
- if (tp->cc_recv != 0 &&
- tp->t_duration < TCPTV_MSL) {
- tp->t_timer[TCPT_2MSL] =
- tp->t_rxtcur * TCPTV_TWTRUNC;
- /* For transaction client, force ACK now. */
- tp->t_flags |= TF_ACKNOW;
- }
- else
- tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
- soisdisconnected(so);
- break;
-
- /*
- * In TIME_WAIT state restart the 2 MSL time_wait timer.
- */
- case TCPS_TIME_WAIT:
- tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
- break;
- }
- }
-#ifdef TCPDEBUG
- if (so->so_options & SO_DEBUG)
- tcp_trace(TA_INPUT, ostate, tp, &tcp_saveti, 0);
-#endif
-
- /*
- * Return any desired output.
- */
- if (needoutput || (tp->t_flags & TF_ACKNOW))
- (void) tcp_output(tp);
- return;
-
-dropafterack:
- /*
- * Generate an ACK dropping incoming segment if it occupies
- * sequence space, where the ACK reflects our state.
- *
- * We can now skip the test for the RST flag since all
- * paths to this code happen after packets containing
- * RST have been dropped.
- *
- * In the SYN-RECEIVED state, don't send an ACK unless the
- * segment we received passes the SYN-RECEIVED ACK test.
- * If it fails send a RST. This breaks the loop in the
- * "LAND" DoS attack, and also prevents an ACK storm
- * between two listening ports that have been sent forged
- * SYN segments, each with the source address of the other.
- */
- if (tp->t_state == TCPS_SYN_RECEIVED && (tiflags & TH_ACK) &&
- (SEQ_GT(tp->snd_una, ti->ti_ack) ||
- SEQ_GT(ti->ti_ack, tp->snd_max)) )
- goto dropwithreset;
-#ifdef TCPDEBUG
- if (so->so_options & SO_DEBUG)
- tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0);
-#endif
- m_freem(m);
- tp->t_flags |= TF_ACKNOW;
- (void) tcp_output(tp);
- return;
-
-dropwithreset:
- /*
- * Generate a RST, dropping incoming segment.
- * Make ACK acceptable to originator of segment.
- * Don't bother to respond if destination was broadcast/multicast.
- */
- if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST) ||
- IN_MULTICAST(ntohl(ti->ti_dst.s_addr)))
- goto drop;
-#ifdef TCPDEBUG
- if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
- tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0);
-#endif
- if (tiflags & TH_ACK)
- tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
- else {
- if (tiflags & TH_SYN)
- ti->ti_len++;
- tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
- TH_RST|TH_ACK);
- }
- /* destroy temporarily created socket */
- if (dropsocket)
- (void) soabort(so);
- return;
-
-drop:
- /*
- * Drop space held by incoming segment and return.
- */
-#ifdef TCPDEBUG
- if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
- tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0);
-#endif
- m_freem(m);
- /* destroy temporarily created socket */
- if (dropsocket)
- (void) soabort(so);
- return;
-}
-
-static void
-tcp_dooptions(tp, cp, cnt, ti, to)
- struct tcpcb *tp;
- u_char *cp;
- int cnt;
- struct tcpiphdr *ti;
- struct tcpopt *to;
-{
- u_short mss = 0;
- int opt, optlen;
-
- for (; cnt > 0; cnt -= optlen, cp += optlen) {
- opt = cp[0];
- if (opt == TCPOPT_EOL)
- break;
- if (opt == TCPOPT_NOP)
- optlen = 1;
- else {
- optlen = cp[1];
- if (optlen <= 0)
- break;
- }
- switch (opt) {
-
- default:
- continue;
-
- case TCPOPT_MAXSEG:
- if (optlen != TCPOLEN_MAXSEG)
- continue;
- if (!(ti->ti_flags & TH_SYN))
- continue;
- bcopy((char *) cp + 2, (char *) &mss, sizeof(mss));
- NTOHS(mss);
- break;
-
- case TCPOPT_WINDOW:
- if (optlen != TCPOLEN_WINDOW)
- continue;
- if (!(ti->ti_flags & TH_SYN))
- continue;
- tp->t_flags |= TF_RCVD_SCALE;
- tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT);
- break;
-
- case TCPOPT_TIMESTAMP:
- if (optlen != TCPOLEN_TIMESTAMP)
- continue;
- to->to_flag |= TOF_TS;
- bcopy((char *)cp + 2,
- (char *)&to->to_tsval, sizeof(to->to_tsval));
- NTOHL(to->to_tsval);
- bcopy((char *)cp + 6,
- (char *)&to->to_tsecr, sizeof(to->to_tsecr));
- NTOHL(to->to_tsecr);
-
- /*
- * A timestamp received in a SYN makes
- * it ok to send timestamp requests and replies.
- */
- if (ti->ti_flags & TH_SYN) {
- tp->t_flags |= TF_RCVD_TSTMP;
- tp->ts_recent = to->to_tsval;
- tp->ts_recent_age = tcp_now;
- }
- break;
- case TCPOPT_CC:
- if (optlen != TCPOLEN_CC)
- continue;
- to->to_flag |= TOF_CC;
- bcopy((char *)cp + 2,
- (char *)&to->to_cc, sizeof(to->to_cc));
- NTOHL(to->to_cc);
- /*
- * A CC or CC.new option received in a SYN makes
- * it ok to send CC in subsequent segments.
- */
- if (ti->ti_flags & TH_SYN)
- tp->t_flags |= TF_RCVD_CC;
- break;
- case TCPOPT_CCNEW:
- if (optlen != TCPOLEN_CC)
- continue;
- if (!(ti->ti_flags & TH_SYN))
- continue;
- to->to_flag |= TOF_CCNEW;
- bcopy((char *)cp + 2,
- (char *)&to->to_cc, sizeof(to->to_cc));
- NTOHL(to->to_cc);
- /*
- * A CC or CC.new option received in a SYN makes
- * it ok to send CC in subsequent segments.
- */
- tp->t_flags |= TF_RCVD_CC;
- break;
- case TCPOPT_CCECHO:
- if (optlen != TCPOLEN_CC)
- continue;
- if (!(ti->ti_flags & TH_SYN))
- continue;
- to->to_flag |= TOF_CCECHO;
- bcopy((char *)cp + 2,
- (char *)&to->to_ccecho, sizeof(to->to_ccecho));
- NTOHL(to->to_ccecho);
- break;
- }
- }
- if (ti->ti_flags & TH_SYN)
- tcp_mss(tp, mss); /* sets t_maxseg */
-}
-
-/*
- * Pull out of band byte out of a segment so
- * it doesn't appear in the user's data queue.
- * It is still reflected in the segment length for
- * sequencing purposes.
- */
-static void
-tcp_pulloutofband(so, ti, m)
- struct socket *so;
- struct tcpiphdr *ti;
- register struct mbuf *m;
-{
- int cnt = ti->ti_urp - 1;
-
- while (cnt >= 0) {
- if (m->m_len > cnt) {
- char *cp = mtod(m, caddr_t) + cnt;
- struct tcpcb *tp = sototcpcb(so);
-
- tp->t_iobc = *cp;
- tp->t_oobflags |= TCPOOB_HAVEDATA;
- bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1));
- m->m_len--;
- return;
- }
- cnt -= m->m_len;
- m = m->m_next;
- if (m == 0)
- break;
- }
- panic("tcp_pulloutofband");
-}
-
-/*
- * Collect new round-trip time estimate
- * and update averages and current timeout.
- */
-static void
-tcp_xmit_timer(tp, rtt)
- register struct tcpcb *tp;
- short rtt;
-{
- register int delta;
-
- tcpstat.tcps_rttupdated++;
- tp->t_rttupdated++;
- if (tp->t_srtt != 0) {
- /*
- * srtt is stored as fixed point with 5 bits after the
- * binary point (i.e., scaled by 8). The following magic
- * is equivalent to the smoothing algorithm in rfc793 with
- * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed
- * point). Adjust rtt to origin 0.
- */
- delta = ((rtt - 1) << TCP_DELTA_SHIFT)
- - (tp->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT));
-
- if ((tp->t_srtt += delta) <= 0)
- tp->t_srtt = 1;
-
- /*
- * We accumulate a smoothed rtt variance (actually, a
- * smoothed mean difference), then set the retransmit
- * timer to smoothed rtt + 4 times the smoothed variance.
- * rttvar is stored as fixed point with 4 bits after the
- * binary point (scaled by 16). The following is
- * equivalent to rfc793 smoothing with an alpha of .75
- * (rttvar = rttvar*3/4 + |delta| / 4). This replaces
- * rfc793's wired-in beta.
- */
- if (delta < 0)
- delta = -delta;
- delta -= tp->t_rttvar >> (TCP_RTTVAR_SHIFT - TCP_DELTA_SHIFT);
- if ((tp->t_rttvar += delta) <= 0)
- tp->t_rttvar = 1;
- } else {
- /*
- * No rtt measurement yet - use the unsmoothed rtt.
- * Set the variance to half the rtt (so our first
- * retransmit happens at 3*rtt).
- */
- tp->t_srtt = rtt << TCP_RTT_SHIFT;
- tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1);
- }
- tp->t_rtt = 0;
- tp->t_rxtshift = 0;
-
- /*
- * the retransmit should happen at rtt + 4 * rttvar.
- * Because of the way we do the smoothing, srtt and rttvar
- * will each average +1/2 tick of bias. When we compute
- * the retransmit timer, we want 1/2 tick of rounding and
- * 1 extra tick because of +-1/2 tick uncertainty in the
- * firing of the timer. The bias will give us exactly the
- * 1.5 tick we need. But, because the bias is
- * statistical, we have to test that we don't drop below
- * the minimum feasible timer (which is 2 ticks).
- */
- TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
- max(tp->t_rttmin, rtt + 2), TCPTV_REXMTMAX);
-
- /*
- * We received an ack for a packet that wasn't retransmitted;
- * it is probably safe to discard any error indications we've
- * received recently. This isn't quite right, but close enough
- * for now (a route might have failed after we sent a segment,
- * and the return path might not be symmetrical).
- */
- tp->t_softerror = 0;
-}
-
-/*
- * Determine a reasonable value for maxseg size.
- * If the route is known, check route for mtu.
- * If none, use an mss that can be handled on the outgoing
- * interface without forcing IP to fragment; if bigger than
- * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES
- * to utilize large mbufs. If no route is found, route has no mtu,
- * or the destination isn't local, use a default, hopefully conservative
- * size (usually 512 or the default IP max size, but no more than the mtu
- * of the interface), as we can't discover anything about intervening
- * gateways or networks. We also initialize the congestion/slow start
- * window to be a single segment if the destination isn't local.
- * While looking at the routing entry, we also initialize other path-dependent
- * parameters from pre-set or cached values in the routing entry.
- *
- * Also take into account the space needed for options that we
- * send regularly. Make maxseg shorter by that amount to assure
- * that we can send maxseg amount of data even when the options
- * are present. Store the upper limit of the length of options plus
- * data in maxopd.
- *
- * NOTE that this routine is only called when we process an incoming
- * segment, for outgoing segments only tcp_mssopt is called.
- *
- * In case of T/TCP, we call this routine during implicit connection
- * setup as well (offer = -1), to initialize maxseg from the cached
- * MSS of our peer.
- */
-void
-tcp_mss(tp, offer)
- struct tcpcb *tp;
- int offer;
-{
- register struct rtentry *rt;
- struct ifnet *ifp;
- register int rtt, mss;
- u_long bufsize;
- struct inpcb *inp;
- struct socket *so;
- struct rmxp_tao *taop;
- int origoffer = offer;
-
- inp = tp->t_inpcb;
- if ((rt = tcp_rtlookup(inp)) == NULL) {
- tp->t_maxopd = tp->t_maxseg = tcp_mssdflt;
- return;
- }
- ifp = rt->rt_ifp;
- so = inp->inp_socket;
-
- taop = rmx_taop(rt->rt_rmx);
- /*
- * Offer == -1 means that we didn't receive SYN yet,
- * use cached value in that case;
- */
- if (offer == -1)
- offer = taop->tao_mssopt;
- /*
- * Offer == 0 means that there was no MSS on the SYN segment,
- * in this case we use tcp_mssdflt.
- */
- if (offer == 0)
- offer = tcp_mssdflt;
- else
- /*
- * Sanity check: make sure that maxopd will be large
- * enough to allow some data on segments even is the
- * all the option space is used (40bytes). Otherwise
- * funny things may happen in tcp_output.
- */
- offer = max(offer, 64);
- taop->tao_mssopt = offer;
-
- /*
- * While we're here, check if there's an initial rtt
- * or rttvar. Convert from the route-table units
- * to scaled multiples of the slow timeout timer.
- */
- if (tp->t_srtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) {
- /*
- * XXX the lock bit for RTT indicates that the value
- * is also a minimum value; this is subject to time.
- */
- if (rt->rt_rmx.rmx_locks & RTV_RTT)
- tp->t_rttmin = rtt / (RTM_RTTUNIT / PR_SLOWHZ);
- tp->t_srtt = rtt / (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
- tcpstat.tcps_usedrtt++;
- if (rt->rt_rmx.rmx_rttvar) {
- tp->t_rttvar = rt->rt_rmx.rmx_rttvar /
- (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
- tcpstat.tcps_usedrttvar++;
- } else {
- /* default variation is +- 1 rtt */
- tp->t_rttvar =
- tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE;
- }
- TCPT_RANGESET(tp->t_rxtcur,
- ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1,
- tp->t_rttmin, TCPTV_REXMTMAX);
- }
- /*
- * if there's an mtu associated with the route, use it
- */
- if (rt->rt_rmx.rmx_mtu)
- mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr);
- else
- {
- mss = ifp->if_mtu - sizeof(struct tcpiphdr);
- if (!in_localaddr(inp->inp_faddr))
- mss = min(mss, tcp_mssdflt);
- }
- mss = min(mss, offer);
- /*
- * maxopd stores the maximum length of data AND options
- * in a segment; maxseg is the amount of data in a normal
- * segment. We need to store this value (maxopd) apart
- * from maxseg, because now every segment carries options
- * and thus we normally have somewhat less data in segments.
- */
- tp->t_maxopd = mss;
-
- /*
- * In case of T/TCP, origoffer==-1 indicates, that no segments
- * were received yet. In this case we just guess, otherwise
- * we do the same as before T/TCP.
- */
- if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
- (origoffer == -1 ||
- (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP))
- mss -= TCPOLEN_TSTAMP_APPA;
- if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
- (origoffer == -1 ||
- (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC))
- mss -= TCPOLEN_CC_APPA;
-
-#if (MCLBYTES & (MCLBYTES - 1)) == 0
- if (mss > MCLBYTES)
- mss &= ~(MCLBYTES-1);
-#else
- if (mss > MCLBYTES)
- mss = mss / MCLBYTES * MCLBYTES;
-#endif
- /*
- * If there's a pipesize, change the socket buffer
- * to that size. Make the socket buffers an integral
- * number of mss units; if the mss is larger than
- * the socket buffer, decrease the mss.
- */
-#ifdef RTV_SPIPE
- if ((bufsize = rt->rt_rmx.rmx_sendpipe) == 0)
-#endif
- bufsize = so->so_snd.sb_hiwat;
- if (bufsize < mss)
- mss = bufsize;
- else {
- bufsize = roundup(bufsize, mss);
- if (bufsize > sb_max)
- bufsize = sb_max;
- (void)sbreserve(&so->so_snd, bufsize);
- }
- tp->t_maxseg = mss;
-
-#ifdef RTV_RPIPE
- if ((bufsize = rt->rt_rmx.rmx_recvpipe) == 0)
-#endif
- bufsize = so->so_rcv.sb_hiwat;
- if (bufsize > mss) {
- bufsize = roundup(bufsize, mss);
- if (bufsize > sb_max)
- bufsize = sb_max;
- (void)sbreserve(&so->so_rcv, bufsize);
- }
- /*
- * Don't force slow-start on local network.
- */
- if (!in_localaddr(inp->inp_faddr))
- tp->snd_cwnd = mss;
-
- if (rt->rt_rmx.rmx_ssthresh) {
- /*
- * There's some sort of gateway or interface
- * buffer limit on the path. Use this to set
- * the slow start threshhold, but set the
- * threshold to no less than 2*mss.
- */
- tp->snd_ssthresh = max(2 * mss, rt->rt_rmx.rmx_ssthresh);
- tcpstat.tcps_usedssthresh++;
- }
-}
-
-/*
- * Determine the MSS option to send on an outgoing SYN.
- */
-int
-tcp_mssopt(tp)
- struct tcpcb *tp;
-{
- struct rtentry *rt;
-
- rt = tcp_rtlookup(tp->t_inpcb);
- if (rt == NULL)
- return tcp_mssdflt;
-
- return rt->rt_ifp->if_mtu - sizeof(struct tcpiphdr);
-}
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
deleted file mode 100644
index 12ca0258f12f..000000000000
--- a/sys/netinet/tcp_timewait.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
- * The Regents of the University of California. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
- *
- * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95
- * $Id: tcp_subr.c,v 1.48 1998/11/15 21:35:09 guido Exp $
- */
-
-#include "opt_compat.h"
-#include "opt_tcpdebug.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/protosw.h>
-
-#include <vm/vm_zone.h>
-
-#include <net/route.h>
-#include <net/if.h>
-
-#define _IP_VHL
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_pcb.h>
-#include <netinet/in_var.h>
-#include <netinet/ip_var.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_fsm.h>
-#include <netinet/tcp_seq.h>
-#include <netinet/tcp_timer.h>
-#include <netinet/tcp_var.h>
-#include <netinet/tcpip.h>
-#ifdef TCPDEBUG
-#include <netinet/tcp_debug.h>
-#endif
-
-int tcp_mssdflt = TCP_MSS;
-SYSCTL_INT(_net_inet_tcp, TCPCTL_MSSDFLT, mssdflt,
- CTLFLAG_RW, &tcp_mssdflt , 0, "");
-
-static int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
-SYSCTL_INT(_net_inet_tcp, TCPCTL_RTTDFLT, rttdflt,
- CTLFLAG_RW, &tcp_rttdflt , 0, "");
-
-static int tcp_do_rfc1323 = 1;
-SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323,
- CTLFLAG_RW, &tcp_do_rfc1323 , 0, "");
-
-static int tcp_do_rfc1644 = 0;
-SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1644, rfc1644,
- CTLFLAG_RW, &tcp_do_rfc1644 , 0, "");
-
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD, &tcbinfo.ipi_count,
- 0, "Number of active PCBs");
-
-static void tcp_cleartaocache __P((void));
-static void tcp_notify __P((struct inpcb *, int));
-
-/*
- * Target size of TCP PCB hash tables. Must be a power of two.
- */
-#ifndef TCBHASHSIZE
-#define TCBHASHSIZE 512
-#endif
-
-/*
- * This is the actual shape of what we allocate using the zone
- * allocator. Doing it this way allows us to protect both structures
- * using the same generation count, and also eliminates the overhead
- * of allocating tcpcbs separately. By hiding the structure here,
- * we avoid changing most of the rest of the code (although it needs
- * to be changed, eventually, for greater efficiency).
- */
-#define ALIGNMENT 32
-#define ALIGNM1 (ALIGNMENT - 1)
-struct inp_tp {
- union {
- struct inpcb inp;
- char align[(sizeof(struct inpcb) + ALIGNM1) & ~ALIGNM1];
- } inp_tp_u;
- struct tcpcb tcb;
-};
-#undef ALIGNMENT
-#undef ALIGNM1
-
-/*
- * Tcp initialization
- */
-void
-tcp_init()
-{
-
- tcp_iss = random(); /* wrong, but better than a constant */
- tcp_ccgen = 1;
- tcp_cleartaocache();
- LIST_INIT(&tcb);
- tcbinfo.listhead = &tcb;
- tcbinfo.hashbase = hashinit(TCBHASHSIZE, M_PCB, &tcbinfo.hashmask);
- tcbinfo.porthashbase = hashinit(TCBHASHSIZE, M_PCB,
- &tcbinfo.porthashmask);
- tcbinfo.ipi_zone = zinit("tcpcb", sizeof(struct inp_tp), maxsockets,
- ZONE_INTERRUPT, 0);
- if (max_protohdr < sizeof(struct tcpiphdr))
- max_protohdr = sizeof(struct tcpiphdr);
- if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN)
- panic("tcp_init");
-}
-
-/*
- * Create template to be used to send tcp packets on a connection.
- * Call after host entry created, allocates an mbuf and fills
- * in a skeletal tcp/ip header, minimizing the amount of work
- * necessary when the connection is used.
- */
-struct tcpiphdr *
-tcp_template(tp)
- struct tcpcb *tp;
-{
- register struct inpcb *inp = tp->t_inpcb;
- register struct mbuf *m;
- register struct tcpiphdr *n;
-
- if ((n = tp->t_template) == 0) {
- m = m_get(M_DONTWAIT, MT_HEADER);
- if (m == NULL)
- return (0);
- m->m_len = sizeof (struct tcpiphdr);
- n = mtod(m, struct tcpiphdr *);
- }
- bzero(n->ti_x1, sizeof(n->ti_x1));
- n->ti_pr = IPPROTO_TCP;
- n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
- n->ti_src = inp->inp_laddr;
- n->ti_dst = inp->inp_faddr;
- n->ti_sport = inp->inp_lport;
- n->ti_dport = inp->inp_fport;
- n->ti_seq = 0;
- n->ti_ack = 0;
- n->ti_x2 = 0;
- n->ti_off = 5;
- n->ti_flags = 0;
- n->ti_win = 0;
- n->ti_sum = 0;
- n->ti_urp = 0;
- return (n);
-}
-
-/*
- * Send a single message to the TCP at address specified by
- * the given TCP/IP header. If m == 0, then we make a copy
- * of the tcpiphdr at ti and send directly to the addressed host.
- * This is used to force keep alive messages out using the TCP
- * template for a connection tp->t_template. If flags are given
- * then we send a message back to the TCP which originated the
- * segment ti, and discard the mbuf containing it and any other
- * attached mbufs.
- *
- * In any case the ack and sequence number of the transmitted
- * segment are as specified by the parameters.
- *
- * NOTE: If m != NULL, then ti must point to *inside* the mbuf.
- */
-void
-tcp_respond(tp, ti, m, ack, seq, flags)
- struct tcpcb *tp;
- register struct tcpiphdr *ti;
- register struct mbuf *m;
- tcp_seq ack, seq;
- int flags;
-{
- register int tlen;
- int win = 0;
- struct route *ro = 0;
- struct route sro;
-
- if (tp) {
- if (!(flags & TH_RST))
- win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
- ro = &tp->t_inpcb->inp_route;
- } else {
- ro = &sro;
- bzero(ro, sizeof *ro);
- }
- if (m == 0) {
- m = m_gethdr(M_DONTWAIT, MT_HEADER);
- if (m == NULL)
- return;
-#ifdef TCP_COMPAT_42
- tlen = 1;
-#else
- tlen = 0;
-#endif
- m->m_data += max_linkhdr;
- *mtod(m, struct tcpiphdr *) = *ti;
- ti = mtod(m, struct tcpiphdr *);
- flags = TH_ACK;
- } else {
- m_freem(m->m_next);
- m->m_next = 0;
- m->m_data = (caddr_t)ti;
- m->m_len = sizeof (struct tcpiphdr);
- tlen = 0;
-#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
- xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, n_long);
- xchg(ti->ti_dport, ti->ti_sport, n_short);
-#undef xchg
- }
- ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
- tlen += sizeof (struct tcpiphdr);
- m->m_len = tlen;
- m->m_pkthdr.len = tlen;
- m->m_pkthdr.rcvif = (struct ifnet *) 0;
- bzero(ti->ti_x1, sizeof(ti->ti_x1));
- ti->ti_seq = htonl(seq);
- ti->ti_ack = htonl(ack);
- ti->ti_x2 = 0;
- ti->ti_off = sizeof (struct tcphdr) >> 2;
- ti->ti_flags = flags;
- if (tp)
- ti->ti_win = htons((u_short) (win >> tp->rcv_scale));
- else
- ti->ti_win = htons((u_short)win);
- ti->ti_urp = 0;
- ti->ti_sum = 0;
- ti->ti_sum = in_cksum(m, tlen);
- ((struct ip *)ti)->ip_len = tlen;
- ((struct ip *)ti)->ip_ttl = ip_defttl;
-#ifdef TCPDEBUG
- if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
- tcp_trace(TA_OUTPUT, 0, tp, ti, 0);
-#endif
- (void) ip_output(m, NULL, ro, 0, NULL);
- if (ro == &sro && ro->ro_rt) {
- RTFREE(ro->ro_rt);
- }
-}
-
-/*
- * Create a new TCP control block, making an
- * empty reassembly queue and hooking it to the argument
- * protocol control block. The `inp' parameter must have
- * come from the zone allocator set up in tcp_init().
- */
-struct tcpcb *
-tcp_newtcpcb(inp)
- struct inpcb *inp;
-{
- struct inp_tp *it;
- register struct tcpcb *tp;
-
- it = (struct inp_tp *)inp;
- tp = &it->tcb;
- bzero((char *) tp, sizeof(struct tcpcb));
- tp->t_segq = NULL;
- tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
-
- if (tcp_do_rfc1323)
- tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
- if (tcp_do_rfc1644)
- tp->t_flags |= TF_REQ_CC;
- tp->t_inpcb = inp; /* XXX */
- /*
- * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
- * rtt estimate. Set rttvar so that srtt + 4 * rttvar gives
- * reasonable initial retransmit time.
- */
- tp->t_srtt = TCPTV_SRTTBASE;
- tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
- tp->t_rttmin = TCPTV_MIN;
- tp->t_rxtcur = TCPTV_RTOBASE;
- tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
- tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
- inp->inp_ip_ttl = ip_defttl;
- inp->inp_ppcb = (caddr_t)tp;
- return (tp); /* XXX */
-}
-
-/*
- * Drop a TCP connection, reporting
- * the specified error. If connection is synchronized,
- * then send a RST to peer.
- */
-struct tcpcb *
-tcp_drop(tp, errno)
- register struct tcpcb *tp;
- int errno;
-{
- struct socket *so = tp->t_inpcb->inp_socket;
-
- if (TCPS_HAVERCVDSYN(tp->t_state)) {
- tp->t_state = TCPS_CLOSED;
- (void) tcp_output(tp);
- tcpstat.tcps_drops++;
- } else
- tcpstat.tcps_conndrops++;
- if (errno == ETIMEDOUT && tp->t_softerror)
- errno = tp->t_softerror;
- so->so_error = errno;
- return (tcp_close(tp));
-}
-
-/*
- * Close a TCP control block:
- * discard all space held by the tcp
- * discard internet protocol block
- * wake up any sleepers
- */
-struct tcpcb *
-tcp_close(tp)
- register struct tcpcb *tp;
-{
- register struct mbuf *q;
- register struct mbuf *nq;
- struct inpcb *inp = tp->t_inpcb;
- struct socket *so = inp->inp_socket;
- register struct rtentry *rt;
- int dosavessthresh;
-
- /*
- * If we got enough samples through the srtt filter,
- * save the rtt and rttvar in the routing entry.
- * 'Enough' is arbitrarily defined as the 16 samples.
- * 16 samples is enough for the srtt filter to converge
- * to within 5% of the correct value; fewer samples and
- * we could save a very bogus rtt.
- *
- * Don't update the default route's characteristics and don't
- * update anything that the user "locked".
- */
- if (tp->t_rttupdated >= 16 &&
- (rt = inp->inp_route.ro_rt) &&
- ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr != INADDR_ANY) {
- register u_long i = 0;
-
- if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
- i = tp->t_srtt *
- (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
- if (rt->rt_rmx.rmx_rtt && i)
- /*
- * filter this update to half the old & half
- * the new values, converting scale.
- * See route.h and tcp_var.h for a
- * description of the scaling constants.
- */
- rt->rt_rmx.rmx_rtt =
- (rt->rt_rmx.rmx_rtt + i) / 2;
- else
- rt->rt_rmx.rmx_rtt = i;
- tcpstat.tcps_cachedrtt++;
- }
- if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
- i = tp->t_rttvar *
- (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
- if (rt->rt_rmx.rmx_rttvar && i)
- rt->rt_rmx.rmx_rttvar =
- (rt->rt_rmx.rmx_rttvar + i) / 2;
- else
- rt->rt_rmx.rmx_rttvar = i;
- tcpstat.tcps_cachedrttvar++;
- }
- /*
- * The old comment here said:
- * update the pipelimit (ssthresh) if it has been updated
- * already or if a pipesize was specified & the threshhold
- * got below half the pipesize. I.e., wait for bad news
- * before we start updating, then update on both good
- * and bad news.
- *
- * But we want to save the ssthresh even if no pipesize is
- * specified explicitly in the route, because such
- * connections still have an implicit pipesize specified
- * by the global tcp_sendspace. In the absence of a reliable
- * way to calculate the pipesize, it will have to do.
- */
- i = tp->snd_ssthresh;
- if (rt->rt_rmx.rmx_sendpipe != 0)
- dosavessthresh = (i < rt->rt_rmx.rmx_sendpipe / 2);
- else
- dosavessthresh = (i < so->so_snd.sb_hiwat / 2);
- if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
- i != 0 && rt->rt_rmx.rmx_ssthresh != 0)
- || dosavessthresh) {
- /*
- * convert the limit from user data bytes to
- * packets then to packet data bytes.
- */
- i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
- if (i < 2)
- i = 2;
- i *= (u_long)(tp->t_maxseg + sizeof (struct tcpiphdr));
- if (rt->rt_rmx.rmx_ssthresh)
- rt->rt_rmx.rmx_ssthresh =
- (rt->rt_rmx.rmx_ssthresh + i) / 2;
- else
- rt->rt_rmx.rmx_ssthresh = i;
- tcpstat.tcps_cachedssthresh++;
- }
- }
- /* free the reassembly queue, if any */
- for (q = tp->t_segq; q; q = nq) {
- nq = q->m_nextpkt;
- tp->t_segq = nq;
- m_freem(q);
- }
- if (tp->t_template)
- (void) m_free(dtom(tp->t_template));
- inp->inp_ppcb = NULL;
- soisdisconnected(so);
- in_pcbdetach(inp);
- tcpstat.tcps_closed++;
- return ((struct tcpcb *)0);
-}
-
-void
-tcp_drain()
-{
-
-}
-
-/*
- * Notify a tcp user of an asynchronous error;
- * store error as soft error, but wake up user
- * (for now, won't do anything until can select for soft error).
- */
-static void
-tcp_notify(inp, error)
- struct inpcb *inp;
- int error;
-{
- register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
- register struct socket *so = inp->inp_socket;
-
- /*
- * Ignore some errors if we are hooked up.
- * If connection hasn't completed, has retransmitted several times,
- * and receives a second error, give up now. This is better
- * than waiting a long time to establish a connection that
- * can never complete.
- */
- if (tp->t_state == TCPS_ESTABLISHED &&
- (error == EHOSTUNREACH || error == ENETUNREACH ||
- error == EHOSTDOWN)) {
- return;
- } else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
- tp->t_softerror)
- so->so_error = error;
- else
- tp->t_softerror = error;
- wakeup((caddr_t) &so->so_timeo);
- sorwakeup(so);
- sowwakeup(so);
-}
-
-static int
-tcp_pcblist SYSCTL_HANDLER_ARGS
-{
- int error, i, n, s;
- struct inpcb *inp, **inp_list;
- inp_gen_t gencnt;
- struct xinpgen xig;
-
- /*
- * The process of preparing the TCB list is too time-consuming and
- * resource-intensive to repeat twice on every request.
- */
- if (req->oldptr == 0) {
- n = tcbinfo.ipi_count;
- req->oldidx = 2 * (sizeof xig)
- + (n + n/8) * sizeof(struct xtcpcb);
- return 0;
- }
-
- if (req->newptr != 0)
- return EPERM;
-
- /*
- * OK, now we're committed to doing something.
- */
- s = splnet();
- gencnt = tcbinfo.ipi_gencnt;
- n = tcbinfo.ipi_count;
- splx(s);
-
- xig.xig_len = sizeof xig;
- xig.xig_count = n;
- xig.xig_gen = gencnt;
- xig.xig_sogen = so_gencnt;
- error = SYSCTL_OUT(req, &xig, sizeof xig);
- if (error)
- return error;
-
- inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
- if (inp_list == 0)
- return ENOMEM;
-
- s = splnet();
- for (inp = tcbinfo.listhead->lh_first, i = 0; inp && i < n;
- inp = inp->inp_list.le_next) {
- if (inp->inp_gencnt <= gencnt)
- inp_list[i++] = inp;
- }
- splx(s);
- n = i;
-
- error = 0;
- for (i = 0; i < n; i++) {
- inp = inp_list[i];
- if (inp->inp_gencnt <= gencnt) {
- struct xtcpcb xt;
- xt.xt_len = sizeof xt;
- /* XXX should avoid extra copy */
- bcopy(inp, &xt.xt_inp, sizeof *inp);
- bcopy(inp->inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp);
- if (inp->inp_socket)
- sotoxsocket(inp->inp_socket, &xt.xt_socket);
- error = SYSCTL_OUT(req, &xt, sizeof xt);
- }
- }
- if (!error) {
- /*
- * Give the user an updated idea of our state.
- * If the generation differs from what we told
- * her before, she knows that something happened
- * while we were processing this request, and it
- * might be necessary to retry.
- */
- s = splnet();
- xig.xig_gen = tcbinfo.ipi_gencnt;
- xig.xig_sogen = so_gencnt;
- xig.xig_count = tcbinfo.ipi_count;
- splx(s);
- error = SYSCTL_OUT(req, &xig, sizeof xig);
- }
- free(inp_list, M_TEMP);
- return error;
-}
-
-SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
- tcp_pcblist, "S,xtcpcb", "List of active TCP connections");
-
-void
-tcp_ctlinput(cmd, sa, vip)
- int cmd;
- struct sockaddr *sa;
- void *vip;
-{
- register struct ip *ip = vip;
- register struct tcphdr *th;
- void (*notify) __P((struct inpcb *, int)) = tcp_notify;
-
- if (cmd == PRC_QUENCH)
- notify = tcp_quench;
- else if (cmd == PRC_MSGSIZE)
- notify = tcp_mtudisc;
- else if (!PRC_IS_REDIRECT(cmd) &&
- ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0))
- return;
- if (ip) {
- th = (struct tcphdr *)((caddr_t)ip
- + (IP_VHL_HL(ip->ip_vhl) << 2));
- in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
- cmd, notify);
- } else
- in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify);
-}
-
-/*
- * When a source quench is received, close congestion window
- * to one segment. We will gradually open it again as we proceed.
- */
-void
-tcp_quench(inp, errno)
- struct inpcb *inp;
- int errno;
-{
- struct tcpcb *tp = intotcpcb(inp);
-
- if (tp)
- tp->snd_cwnd = tp->t_maxseg;
-}
-
-/*
- * When `need fragmentation' ICMP is received, update our idea of the MSS
- * based on the new value in the route. Also nudge TCP to send something,
- * since we know the packet we just sent was dropped.
- * This duplicates some code in the tcp_mss() function in tcp_input.c.
- */
-void
-tcp_mtudisc(inp, errno)
- struct inpcb *inp;
- int errno;
-{
- struct tcpcb *tp = intotcpcb(inp);
- struct rtentry *rt;
- struct rmxp_tao *taop;
- struct socket *so = inp->inp_socket;
- int offered;
- int mss;
-
- if (tp) {
- rt = tcp_rtlookup(inp);
- if (!rt || !rt->rt_rmx.rmx_mtu) {
- tp->t_maxopd = tp->t_maxseg = tcp_mssdflt;
- return;
- }
- taop = rmx_taop(rt->rt_rmx);
- offered = taop->tao_mssopt;
- mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr);
- if (offered)
- mss = min(mss, offered);
- /*
- * XXX - The above conditional probably violates the TCP
- * spec. The problem is that, since we don't know the
- * other end's MSS, we are supposed to use a conservative
- * default. But, if we do that, then MTU discovery will
- * never actually take place, because the conservative
- * default is much less than the MTUs typically seen
- * on the Internet today. For the moment, we'll sweep
- * this under the carpet.
- *
- * The conservative default might not actually be a problem
- * if the only case this occurs is when sending an initial
- * SYN with options and data to a host we've never talked
- * to before. Then, they will reply with an MSS value which
- * will get recorded and the new parameters should get
- * recomputed. For Further Study.
- */
- if (tp->t_maxopd <= mss)
- return;
- tp->t_maxopd = mss;
-
- if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
- (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)
- mss -= TCPOLEN_TSTAMP_APPA;
- if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
- (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC)
- mss -= TCPOLEN_CC_APPA;
-#if (MCLBYTES & (MCLBYTES - 1)) == 0
- if (mss > MCLBYTES)
- mss &= ~(MCLBYTES-1);
-#else
- if (mss > MCLBYTES)
- mss = mss / MCLBYTES * MCLBYTES;
-#endif
- if (so->so_snd.sb_hiwat < mss)
- mss = so->so_snd.sb_hiwat;
-
- tp->t_maxseg = mss;
-
- tcpstat.tcps_mturesent++;
- tp->t_rtt = 0;
- tp->snd_nxt = tp->snd_una;
- tcp_output(tp);
- }
-}
-
-/*
- * Look-up the routing entry to the peer of this inpcb. If no route
- * is found and it cannot be allocated the return NULL. This routine
- * is called by TCP routines that access the rmx structure and by tcp_mss
- * to get the interface MTU.
- */
-struct rtentry *
-tcp_rtlookup(inp)
- struct inpcb *inp;
-{
- struct route *ro;
- struct rtentry *rt;
-
- ro = &inp->inp_route;
- rt = ro->ro_rt;
- if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
- /* No route yet, so try to acquire one */
- if (inp->inp_faddr.s_addr != INADDR_ANY) {
- ro->ro_dst.sa_family = AF_INET;
- ro->ro_dst.sa_len = sizeof(ro->ro_dst);
- ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
- inp->inp_faddr;
- rtalloc(ro);
- rt = ro->ro_rt;
- }
- }
- return rt;
-}
-
-/*
- * Return a pointer to the cached information about the remote host.
- * The cached information is stored in the protocol specific part of
- * the route metrics.
- */
-struct rmxp_tao *
-tcp_gettaocache(inp)
- struct inpcb *inp;
-{
- struct rtentry *rt = tcp_rtlookup(inp);
-
- /* Make sure this is a host route and is up. */
- if (rt == NULL ||
- (rt->rt_flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST))
- return NULL;
-
- return rmx_taop(rt->rt_rmx);
-}
-
-/*
- * Clear all the TAO cache entries, called from tcp_init.
- *
- * XXX
- * This routine is just an empty one, because we assume that the routing
- * routing tables are initialized at the same time when TCP, so there is
- * nothing in the cache left over.
- */
-static void
-tcp_cleartaocache()
-{
-}