1f987e1bdSBrian Somers /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3fe267a55SPedro F. Giffuni *
4e83aaae3SBrian Somers * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5f987e1bdSBrian Somers * All rights reserved.
6f987e1bdSBrian Somers *
7f987e1bdSBrian Somers * Redistribution and use in source and binary forms, with or without
8f987e1bdSBrian Somers * modification, are permitted provided that the following conditions
9f987e1bdSBrian Somers * are met:
10f987e1bdSBrian Somers * 1. Redistributions of source code must retain the above copyright
11f987e1bdSBrian Somers * notice, this list of conditions and the following disclaimer.
12f987e1bdSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright
13f987e1bdSBrian Somers * notice, this list of conditions and the following disclaimer in the
14f987e1bdSBrian Somers * documentation and/or other materials provided with the distribution.
15f987e1bdSBrian Somers *
16f987e1bdSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17f987e1bdSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18f987e1bdSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19f987e1bdSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20f987e1bdSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21f987e1bdSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22f987e1bdSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23f987e1bdSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24f987e1bdSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25f987e1bdSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26f987e1bdSBrian Somers * SUCH DAMAGE.
27f987e1bdSBrian Somers */
28f987e1bdSBrian Somers
29e2505aa6SMatthew Dillon #include <sys/cdefs.h>
303b160b8bSBrian Somers /*
313b160b8bSBrian Somers Alias.c provides supervisory control for the functions of the
323b160b8bSBrian Somers packet aliasing software. It consists of routines to monitor
333b160b8bSBrian Somers TCP connection state, protocol-specific aliasing routines,
343b160b8bSBrian Somers fragment handling and the following outside world functional
353b160b8bSBrian Somers interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
363b160b8bSBrian Somers PacketAliasIn and PacketAliasOut.
373b160b8bSBrian Somers
383b160b8bSBrian Somers The other C program files are briefly described. The data
393b160b8bSBrian Somers structure framework which holds information needed to translate
403b160b8bSBrian Somers packets is encapsulated in alias_db.c. Data is accessed by
413b160b8bSBrian Somers function calls, so other segments of the program need not know
423b160b8bSBrian Somers about the underlying data structures. Alias_ftp.c contains
433b160b8bSBrian Somers special code for modifying the ftp PORT command used to establish
44680c8244SRuslan Ermilov data connections, while alias_irc.c does the same for IRC
453b160b8bSBrian Somers DCC. Alias_util.c contains a few utility routines.
463b160b8bSBrian Somers
473b160b8bSBrian Somers Version 1.0 August, 1996 (cjm)
483b160b8bSBrian Somers
493b160b8bSBrian Somers Version 1.1 August 20, 1996 (cjm)
503b160b8bSBrian Somers PPP host accepts incoming connections for ports 0 to 1023.
513b160b8bSBrian Somers (Gary Roberts pointed out the need to handle incoming
523b160b8bSBrian Somers connections.)
533b160b8bSBrian Somers
543b160b8bSBrian Somers Version 1.2 September 7, 1996 (cjm)
553b160b8bSBrian Somers Fragment handling error in alias_db.c corrected.
563b160b8bSBrian Somers (Tom Torrance helped fix this problem.)
573b160b8bSBrian Somers
583b160b8bSBrian Somers Version 1.4 September 16, 1996 (cjm)
593b160b8bSBrian Somers - A more generalized method for handling incoming
603b160b8bSBrian Somers connections, without the 0-1023 restriction, is
613b160b8bSBrian Somers implemented in alias_db.c
623b160b8bSBrian Somers - Improved ICMP support in alias.c. Traceroute
633b160b8bSBrian Somers packet streams can now be correctly aliased.
643b160b8bSBrian Somers - TCP connection closing logic simplified in
653b160b8bSBrian Somers alias.c and now allows for additional 1 minute
663b160b8bSBrian Somers "grace period" after FIN or RST is observed.
673b160b8bSBrian Somers
683b160b8bSBrian Somers Version 1.5 September 17, 1996 (cjm)
693b160b8bSBrian Somers Corrected error in handling incoming UDP packets with 0 checksum.
703b160b8bSBrian Somers (Tom Torrance helped fix this problem.)
713b160b8bSBrian Somers
723b160b8bSBrian Somers Version 1.6 September 18, 1996 (cjm)
733b160b8bSBrian Somers Simplified ICMP aliasing scheme. Should now support
743b160b8bSBrian Somers traceroute from Win95 as well as FreeBSD.
753b160b8bSBrian Somers
763b160b8bSBrian Somers Version 1.7 January 9, 1997 (cjm)
773b160b8bSBrian Somers - Out-of-order fragment handling.
783b160b8bSBrian Somers - IP checksum error fixed for ftp transfers
793b160b8bSBrian Somers from aliasing host.
803b160b8bSBrian Somers - Integer return codes added to all
813b160b8bSBrian Somers aliasing/de-aliasing functions.
823b160b8bSBrian Somers - Some obsolete comments cleaned up.
833b160b8bSBrian Somers - Differential checksum computations for
843b160b8bSBrian Somers IP header (TCP, UDP and ICMP were already
853b160b8bSBrian Somers differential).
863b160b8bSBrian Somers
873b160b8bSBrian Somers Version 2.1 May 1997 (cjm)
883b160b8bSBrian Somers - Added support for outgoing ICMP error
893b160b8bSBrian Somers messages.
903b160b8bSBrian Somers - Added two functions PacketAliasIn2()
913b160b8bSBrian Somers and PacketAliasOut2() for dynamic address
923b160b8bSBrian Somers control (e.g. round-robin allocation of
933b160b8bSBrian Somers incoming packets).
943efa11bbSBrian Somers
953efa11bbSBrian Somers Version 2.2 July 1997 (cjm)
963efa11bbSBrian Somers - Rationalized API function names to begin
973efa11bbSBrian Somers with "PacketAlias..."
983efa11bbSBrian Somers - Eliminated PacketAliasIn2() and
993efa11bbSBrian Somers PacketAliasOut2() as poorly conceived.
1003efa11bbSBrian Somers
101374fad8bSMatthew Dillon Version 2.3 Dec 1998 (dillon)
102374fad8bSMatthew Dillon - Major bounds checking additions, see FreeBSD/CVS
103374fad8bSMatthew Dillon
104642e43b3SArchie Cobbs Version 3.1 May, 2000 (salander)
10555a39fc5SRuslan Ermilov - Added hooks to handle PPTP.
10655a39fc5SRuslan Ermilov
107642e43b3SArchie Cobbs Version 3.2 July, 2000 (salander and satoh)
108642e43b3SArchie Cobbs - Added PacketUnaliasOut routine.
109642e43b3SArchie Cobbs - Added hooks to handle RTSP/RTP.
110642e43b3SArchie Cobbs
1118ddc51bcSEivind Eklund See HISTORY file for additional revisions.
1123b160b8bSBrian Somers */
1133b160b8bSBrian Somers
114c649a2e0SGleb Smirnoff #ifdef _KERNEL
115c649a2e0SGleb Smirnoff #include <sys/param.h>
1165910c1c1SPaolo Pisati #include <sys/systm.h>
1175910c1c1SPaolo Pisati #include <sys/mbuf.h>
11837ce2656SPaolo Pisati #include <sys/sysctl.h>
119c649a2e0SGleb Smirnoff #else
1203b160b8bSBrian Somers #include <sys/types.h>
121be4f3cd0SPaolo Pisati #include <stdlib.h>
122c649a2e0SGleb Smirnoff #include <stdio.h>
1235910c1c1SPaolo Pisati #include <ctype.h>
124be4f3cd0SPaolo Pisati #include <dlfcn.h>
125be4f3cd0SPaolo Pisati #include <errno.h>
126be4f3cd0SPaolo Pisati #include <string.h>
127c649a2e0SGleb Smirnoff #endif
1283b160b8bSBrian Somers
1293b160b8bSBrian Somers #include <netinet/in_systm.h>
1303b160b8bSBrian Somers #include <netinet/in.h>
1313b160b8bSBrian Somers #include <netinet/ip.h>
1323b160b8bSBrian Somers #include <netinet/ip_icmp.h>
1333b160b8bSBrian Somers #include <netinet/tcp.h>
1343b160b8bSBrian Somers #include <netinet/udp.h>
1353b160b8bSBrian Somers
136c649a2e0SGleb Smirnoff #ifdef _KERNEL
137c649a2e0SGleb Smirnoff #include <netinet/libalias/alias.h>
13875bc2620SGleb Smirnoff #include <netinet/libalias/alias_local.h>
139be4f3cd0SPaolo Pisati #include <netinet/libalias/alias_mod.h>
140c649a2e0SGleb Smirnoff #else
141be4f3cd0SPaolo Pisati #include <err.h>
1423b160b8bSBrian Somers #include "alias.h"
14375bc2620SGleb Smirnoff #include "alias_local.h"
144be4f3cd0SPaolo Pisati #include "alias_mod.h"
145c649a2e0SGleb Smirnoff #endif
1463b160b8bSBrian Somers
14737ce2656SPaolo Pisati /*
14837ce2656SPaolo Pisati * Define libalias SYSCTL Node
14937ce2656SPaolo Pisati */
15037ce2656SPaolo Pisati #ifdef SYSCTL_NODE
15137ce2656SPaolo Pisati
15237ce2656SPaolo Pisati SYSCTL_DECL(_net_inet);
15337ce2656SPaolo Pisati SYSCTL_DECL(_net_inet_ip);
1547029da5cSPawel Biernacki SYSCTL_NODE(_net_inet_ip, OID_AUTO, alias, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
1557029da5cSPawel Biernacki "Libalias sysctl API");
15637ce2656SPaolo Pisati
15737ce2656SPaolo Pisati #endif
15837ce2656SPaolo Pisati
1592871c501SDag-Erling Smørgrav static __inline int
twowords(void * p)1602871c501SDag-Erling Smørgrav twowords(void *p)
1612871c501SDag-Erling Smørgrav {
162e3e2c216SDag-Erling Smørgrav uint8_t *c = p;
1633b160b8bSBrian Somers
164e3e2c216SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN
165e3e2c216SDag-Erling Smørgrav uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0];
166e3e2c216SDag-Erling Smørgrav uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2];
167e3e2c216SDag-Erling Smørgrav #else
168e3e2c216SDag-Erling Smørgrav uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1];
169e3e2c216SDag-Erling Smørgrav uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3];
170e3e2c216SDag-Erling Smørgrav #endif
171e3e2c216SDag-Erling Smørgrav return (s1 + s2);
1722871c501SDag-Erling Smørgrav }
1733b160b8bSBrian Somers
1743b160b8bSBrian Somers /* TCP Handling Routines
1753b160b8bSBrian Somers
1763b160b8bSBrian Somers TcpMonitorIn() -- These routines monitor TCP connections, and
1777d96f4efSBrian Somers TcpMonitorOut() delete a link when a connection is closed.
1783b160b8bSBrian Somers
17992da29a0SRuslan Ermilov These routines look for SYN, FIN and RST flags to determine when TCP
1803b160b8bSBrian Somers connections open and close. When a TCP connection closes, the data
1813b160b8bSBrian Somers structure containing packet aliasing information is deleted after
1823b160b8bSBrian Somers a timeout period.
1833b160b8bSBrian Somers */
1843b160b8bSBrian Somers
1853b160b8bSBrian Somers /* Local prototypes */
186*0fc7bdc9SRichard Scheffenegger static void TcpMonitorIn(uint16_t, struct alias_link *);
1873b160b8bSBrian Somers
188*0fc7bdc9SRichard Scheffenegger static void TcpMonitorOut(uint16_t, struct alias_link *);
1893b160b8bSBrian Somers
1903b160b8bSBrian Somers static void
TcpMonitorIn(uint16_t th_flags,struct alias_link * lnk)191*0fc7bdc9SRichard Scheffenegger TcpMonitorIn(uint16_t th_flags, struct alias_link *lnk)
1923b160b8bSBrian Somers {
193ed01a582SDag-Erling Smørgrav switch (GetStateIn(lnk)) {
1948ddc51bcSEivind Eklund case ALIAS_TCP_STATE_NOT_CONNECTED:
1954741f3a1SPaolo Pisati if (th_flags & TH_RST)
196ed01a582SDag-Erling Smørgrav SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
1974741f3a1SPaolo Pisati else if (th_flags & TH_SYN)
198ed01a582SDag-Erling Smørgrav SetStateIn(lnk, ALIAS_TCP_STATE_CONNECTED);
19992da29a0SRuslan Ermilov break;
2008ddc51bcSEivind Eklund case ALIAS_TCP_STATE_CONNECTED:
2014741f3a1SPaolo Pisati if (th_flags & (TH_FIN | TH_RST))
202ed01a582SDag-Erling Smørgrav SetStateIn(lnk, ALIAS_TCP_STATE_DISCONNECTED);
2038ddc51bcSEivind Eklund break;
2043b160b8bSBrian Somers }
2053b160b8bSBrian Somers }
2063b160b8bSBrian Somers
2073b160b8bSBrian Somers static void
TcpMonitorOut(uint16_t th_flags,struct alias_link * lnk)208*0fc7bdc9SRichard Scheffenegger TcpMonitorOut(uint16_t th_flags, struct alias_link *lnk)
2093b160b8bSBrian Somers {
210ed01a582SDag-Erling Smørgrav switch (GetStateOut(lnk)) {
2118ddc51bcSEivind Eklund case ALIAS_TCP_STATE_NOT_CONNECTED:
2124741f3a1SPaolo Pisati if (th_flags & TH_RST)
213ed01a582SDag-Erling Smørgrav SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
2144741f3a1SPaolo Pisati else if (th_flags & TH_SYN)
215ed01a582SDag-Erling Smørgrav SetStateOut(lnk, ALIAS_TCP_STATE_CONNECTED);
21692da29a0SRuslan Ermilov break;
2178ddc51bcSEivind Eklund case ALIAS_TCP_STATE_CONNECTED:
2184741f3a1SPaolo Pisati if (th_flags & (TH_FIN | TH_RST))
219ed01a582SDag-Erling Smørgrav SetStateOut(lnk, ALIAS_TCP_STATE_DISCONNECTED);
2208ddc51bcSEivind Eklund break;
2213b160b8bSBrian Somers }
2223b160b8bSBrian Somers }
2233b160b8bSBrian Somers
2243b160b8bSBrian Somers /* Protocol Specific Packet Aliasing Routines
2253b160b8bSBrian Somers
226305d1069SRuslan Ermilov IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2()
227305d1069SRuslan Ermilov IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2()
22880607605SRuslan Ermilov ProtoAliasIn(), ProtoAliasOut()
2293b160b8bSBrian Somers UdpAliasIn(), UdpAliasOut()
2303b160b8bSBrian Somers TcpAliasIn(), TcpAliasOut()
2313b160b8bSBrian Somers
2323b160b8bSBrian Somers These routines handle protocol specific details of packet aliasing.
2333b160b8bSBrian Somers One may observe a certain amount of repetitive arithmetic in these
2343b160b8bSBrian Somers functions, the purpose of which is to compute a revised checksum
2353b160b8bSBrian Somers without actually summing over the entire data packet, which could be
2363b160b8bSBrian Somers unnecessarily time consuming.
2373b160b8bSBrian Somers
2383b160b8bSBrian Somers The purpose of the packet aliasing routines is to replace the source
2393b160b8bSBrian Somers address of the outgoing packet and then correctly put it back for
2403b160b8bSBrian Somers any incoming packets. For TCP and UDP, ports are also re-mapped.
2413b160b8bSBrian Somers
2423b160b8bSBrian Somers For ICMP echo/timestamp requests and replies, the following scheme
243483d2f22SRuslan Ermilov is used: the ID number is replaced by an alias for the outgoing
2443b160b8bSBrian Somers packet.
2453b160b8bSBrian Somers
2463b160b8bSBrian Somers ICMP error messages are handled by looking at the IP fragment
2473b160b8bSBrian Somers in the data section of the message.
2483b160b8bSBrian Somers
2493b160b8bSBrian Somers For TCP and UDP protocols, a port number is chosen for an outgoing
2503b160b8bSBrian Somers packet, and then incoming packets are identified by IP address and
2513b160b8bSBrian Somers port numbers. For TCP packets, there is additional logic in the event
252483d2f22SRuslan Ermilov that sequence and ACK numbers have been altered (as in the case for
2533b160b8bSBrian Somers FTP data port commands).
2543b160b8bSBrian Somers
2553b160b8bSBrian Somers The port numbers used by the packet aliasing module are not true
2563b160b8bSBrian Somers ports in the Unix sense. No sockets are actually bound to ports.
2573b160b8bSBrian Somers They are more correctly thought of as placeholders.
2583b160b8bSBrian Somers
2593b160b8bSBrian Somers All packets go through the aliasing mechanism, whether they come from
2603b160b8bSBrian Somers the gateway machine or other machines on a local area network.
2613b160b8bSBrian Somers */
2623b160b8bSBrian Somers
2633b160b8bSBrian Somers /* Local prototypes */
2645e289f9eSPoul-Henning Kamp static int IcmpAliasIn1(struct libalias *, struct ip *);
2655e289f9eSPoul-Henning Kamp static int IcmpAliasIn2(struct libalias *, struct ip *);
2665e289f9eSPoul-Henning Kamp static int IcmpAliasIn(struct libalias *, struct ip *);
2673b160b8bSBrian Somers
268e7581f0fSPoul-Henning Kamp static int IcmpAliasOut1(struct libalias *, struct ip *, int create);
2695e289f9eSPoul-Henning Kamp static int IcmpAliasOut2(struct libalias *, struct ip *);
270e6bbb691SPoul-Henning Kamp static int IcmpAliasOut(struct libalias *, struct ip *, int create);
2713b160b8bSBrian Somers
272ab0fcfd0SPaolo Pisati static int ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
273bc596e56SAlex Richardson struct ip *pip, u_char ip_p, u_short *ip_sum);
274bc596e56SAlex Richardson static int ProtoAliasOut(struct libalias *la, struct ip *pip,
275ab0fcfd0SPaolo Pisati struct in_addr ip_dst, u_char ip_p, u_short *ip_sum,
276ab0fcfd0SPaolo Pisati int create);
27780607605SRuslan Ermilov
2785e289f9eSPoul-Henning Kamp static int UdpAliasIn(struct libalias *, struct ip *);
279ea29dd92SAlexander Motin static int UdpAliasOut(struct libalias *, struct ip *, int, int create);
2803b160b8bSBrian Somers
2815e289f9eSPoul-Henning Kamp static int TcpAliasIn(struct libalias *, struct ip *);
282e6bbb691SPoul-Henning Kamp static int TcpAliasOut(struct libalias *, struct ip *, int, int create);
2833b160b8bSBrian Somers
2843b160b8bSBrian Somers /*
285305d1069SRuslan Ermilov De-alias incoming echo and timestamp replies.
286305d1069SRuslan Ermilov Alias incoming echo and timestamp requests.
2873b160b8bSBrian Somers */
288effc8e57SLutz Donnerhacke static int
IcmpAliasIn1(struct libalias * la,struct ip * pip)289effc8e57SLutz Donnerhacke IcmpAliasIn1(struct libalias *la, struct ip *pip)
290effc8e57SLutz Donnerhacke {
291ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
2923b160b8bSBrian Somers struct icmp *ic;
2933b160b8bSBrian Somers
2942e6b0786SLutz Donnerhacke LIBALIAS_LOCK_ASSERT(la);
2959fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
2963b160b8bSBrian Somers
2973b160b8bSBrian Somers /* Get source address from ICMP data field and restore original data */
298ed01a582SDag-Erling Smørgrav lnk = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1);
299ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
3003b160b8bSBrian Somers u_short original_id;
3013b160b8bSBrian Somers int accumulate;
3023b160b8bSBrian Somers
303ed01a582SDag-Erling Smørgrav original_id = GetOriginalPort(lnk);
3043b160b8bSBrian Somers
3053b160b8bSBrian Somers /* Adjust ICMP checksum */
3063b160b8bSBrian Somers accumulate = ic->icmp_id;
3073b160b8bSBrian Somers accumulate -= original_id;
30871593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
3093b160b8bSBrian Somers
3103b160b8bSBrian Somers /* Put original sequence number back in */
3113b160b8bSBrian Somers ic->icmp_id = original_id;
3123b160b8bSBrian Somers
3133b160b8bSBrian Somers /* Put original address back into IP header */
3143b160b8bSBrian Somers {
3153b160b8bSBrian Somers struct in_addr original_address;
3163b160b8bSBrian Somers
317ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
3183b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
3192871c501SDag-Erling Smørgrav &original_address, &pip->ip_dst, 2);
3203b160b8bSBrian Somers pip->ip_dst = original_address;
3213b160b8bSBrian Somers }
3223b160b8bSBrian Somers
3233b160b8bSBrian Somers return (PKT_ALIAS_OK);
3243b160b8bSBrian Somers }
3253b160b8bSBrian Somers return (PKT_ALIAS_IGNORED);
3263b160b8bSBrian Somers }
3273b160b8bSBrian Somers
3283b160b8bSBrian Somers /*
3293b160b8bSBrian Somers Alias incoming ICMP error messages containing
3303b160b8bSBrian Somers IP header and first 64 bits of datagram.
3313b160b8bSBrian Somers */
332effc8e57SLutz Donnerhacke static int
IcmpAliasIn2(struct libalias * la,struct ip * pip)333effc8e57SLutz Donnerhacke IcmpAliasIn2(struct libalias *la, struct ip *pip)
334effc8e57SLutz Donnerhacke {
3353b160b8bSBrian Somers struct ip *ip;
3363b160b8bSBrian Somers struct icmp *ic, *ic2;
3373b160b8bSBrian Somers struct udphdr *ud;
3383b160b8bSBrian Somers struct tcphdr *tc;
339ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
3403b160b8bSBrian Somers
3412e6b0786SLutz Donnerhacke LIBALIAS_LOCK_ASSERT(la);
3429fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
343305d1069SRuslan Ermilov ip = &ic->icmp_ip;
3443b160b8bSBrian Somers
3459fa0fd26SDag-Erling Smørgrav ud = (struct udphdr *)ip_next(ip);
3469fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(ip);
3479fa0fd26SDag-Erling Smørgrav ic2 = (struct icmp *)ip_next(ip);
3483b160b8bSBrian Somers
3493b160b8bSBrian Somers if (ip->ip_p == IPPROTO_UDP)
350ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
3513b160b8bSBrian Somers ud->uh_dport, ud->uh_sport,
352642cd09fSRuslan Ermilov IPPROTO_UDP, 0);
3533b160b8bSBrian Somers else if (ip->ip_p == IPPROTO_TCP)
354ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
3553b160b8bSBrian Somers tc->th_dport, tc->th_sport,
356642cd09fSRuslan Ermilov IPPROTO_TCP, 0);
357dfcb634bSBrian Somers else if (ip->ip_p == IPPROTO_ICMP) {
3583b160b8bSBrian Somers if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
359ed01a582SDag-Erling Smørgrav lnk = FindIcmpIn(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
3603b160b8bSBrian Somers else
361ed01a582SDag-Erling Smørgrav lnk = NULL;
362dfcb634bSBrian Somers } else
363ed01a582SDag-Erling Smørgrav lnk = NULL;
3643b160b8bSBrian Somers
365ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
366f0f93429SDag-Erling Smørgrav if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
36761a875d7SRuslan Ermilov int accumulate, accumulate2;
3683b160b8bSBrian Somers struct in_addr original_address;
3693b160b8bSBrian Somers u_short original_port;
3703b160b8bSBrian Somers
371ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
372ed01a582SDag-Erling Smørgrav original_port = GetOriginalPort(lnk);
3733b160b8bSBrian Somers
3743b160b8bSBrian Somers /* Adjust ICMP checksum */
3752871c501SDag-Erling Smørgrav accumulate = twowords(&ip->ip_src);
3762871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
3773b160b8bSBrian Somers accumulate += ud->uh_sport;
3783b160b8bSBrian Somers accumulate -= original_port;
37961a875d7SRuslan Ermilov accumulate2 = accumulate;
38061a875d7SRuslan Ermilov accumulate2 += ip->ip_sum;
38161a875d7SRuslan Ermilov ADJUST_CHECKSUM(accumulate, ip->ip_sum);
38261a875d7SRuslan Ermilov accumulate2 -= ip->ip_sum;
38361a875d7SRuslan Ermilov ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
3843b160b8bSBrian Somers
3853b160b8bSBrian Somers /* Un-alias address in IP header */
3863b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
3872871c501SDag-Erling Smørgrav &original_address, &pip->ip_dst, 2);
3883b160b8bSBrian Somers pip->ip_dst = original_address;
3893b160b8bSBrian Somers
390effc8e57SLutz Donnerhacke /* Un-alias address and port number of
391effc8e57SLutz Donnerhacke * original IP packet fragment contained
392effc8e57SLutz Donnerhacke * in ICMP data section */
3933b160b8bSBrian Somers ip->ip_src = original_address;
3943b160b8bSBrian Somers ud->uh_sport = original_port;
395f0f93429SDag-Erling Smørgrav } else if (ip->ip_p == IPPROTO_ICMP) {
39661a875d7SRuslan Ermilov int accumulate, accumulate2;
3973b160b8bSBrian Somers struct in_addr original_address;
3983b160b8bSBrian Somers u_short original_id;
3993b160b8bSBrian Somers
400ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
401ed01a582SDag-Erling Smørgrav original_id = GetOriginalPort(lnk);
4023b160b8bSBrian Somers
4033b160b8bSBrian Somers /* Adjust ICMP checksum */
4042871c501SDag-Erling Smørgrav accumulate = twowords(&ip->ip_src);
4052871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
4063b160b8bSBrian Somers accumulate += ic2->icmp_id;
4073b160b8bSBrian Somers accumulate -= original_id;
40861a875d7SRuslan Ermilov accumulate2 = accumulate;
40961a875d7SRuslan Ermilov accumulate2 += ip->ip_sum;
41061a875d7SRuslan Ermilov ADJUST_CHECKSUM(accumulate, ip->ip_sum);
41161a875d7SRuslan Ermilov accumulate2 -= ip->ip_sum;
41261a875d7SRuslan Ermilov ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
4133b160b8bSBrian Somers
4143b160b8bSBrian Somers /* Un-alias address in IP header */
4153b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
4162871c501SDag-Erling Smørgrav &original_address, &pip->ip_dst, 2);
4173b160b8bSBrian Somers pip->ip_dst = original_address;
4183b160b8bSBrian Somers
419effc8e57SLutz Donnerhacke /* Un-alias address of original IP packet and
420effc8e57SLutz Donnerhacke * sequence number of embedded ICMP datagram */
4213b160b8bSBrian Somers ip->ip_src = original_address;
4223b160b8bSBrian Somers ic2->icmp_id = original_id;
4233b160b8bSBrian Somers }
4243b160b8bSBrian Somers return (PKT_ALIAS_OK);
4253b160b8bSBrian Somers }
4263b160b8bSBrian Somers return (PKT_ALIAS_IGNORED);
4273b160b8bSBrian Somers }
4283b160b8bSBrian Somers
4293b160b8bSBrian Somers static int
IcmpAliasIn(struct libalias * la,struct ip * pip)4305e289f9eSPoul-Henning Kamp IcmpAliasIn(struct libalias *la, struct ip *pip)
4313b160b8bSBrian Somers {
4323b160b8bSBrian Somers struct icmp *ic;
433be597269SAlex Richardson int iresult;
434be597269SAlex Richardson size_t dlen;
4353b160b8bSBrian Somers
436ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
4376461c83eSEd Maste
4386461c83eSEd Maste dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
4396461c83eSEd Maste if (dlen < ICMP_MINLEN)
4406461c83eSEd Maste return (PKT_ALIAS_IGNORED);
4416461c83eSEd Maste
4427d96f4efSBrian Somers /* Return if proxy-only mode is enabled */
4435e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
444ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
4457d96f4efSBrian Somers
4469fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
4473b160b8bSBrian Somers
4483b160b8bSBrian Somers iresult = PKT_ALIAS_IGNORED;
449f0f93429SDag-Erling Smørgrav switch (ic->icmp_type) {
4503b160b8bSBrian Somers case ICMP_ECHOREPLY:
4513b160b8bSBrian Somers case ICMP_TSTAMPREPLY:
452f0f93429SDag-Erling Smørgrav if (ic->icmp_code == 0) {
4535e289f9eSPoul-Henning Kamp iresult = IcmpAliasIn1(la, pip);
4543b160b8bSBrian Somers }
4553b160b8bSBrian Somers break;
4563b160b8bSBrian Somers case ICMP_UNREACH:
4573b160b8bSBrian Somers case ICMP_SOURCEQUENCH:
4583b160b8bSBrian Somers case ICMP_TIMXCEED:
4593b160b8bSBrian Somers case ICMP_PARAMPROB:
4606461c83eSEd Maste if (dlen < ICMP_ADVLENMIN ||
461be597269SAlex Richardson dlen < (size_t)ICMP_ADVLEN(ic))
4626461c83eSEd Maste return (PKT_ALIAS_IGNORED);
4635e289f9eSPoul-Henning Kamp iresult = IcmpAliasIn2(la, pip);
4643b160b8bSBrian Somers break;
4653b160b8bSBrian Somers case ICMP_ECHO:
4663b160b8bSBrian Somers case ICMP_TSTAMP:
4675e289f9eSPoul-Henning Kamp iresult = IcmpAliasIn1(la, pip);
4683b160b8bSBrian Somers break;
4693b160b8bSBrian Somers }
4703b160b8bSBrian Somers return (iresult);
4713b160b8bSBrian Somers }
4723b160b8bSBrian Somers
4733b160b8bSBrian Somers /*
474305d1069SRuslan Ermilov Alias outgoing echo and timestamp requests.
475305d1069SRuslan Ermilov De-alias outgoing echo and timestamp replies.
4763b160b8bSBrian Somers */
477effc8e57SLutz Donnerhacke static int
IcmpAliasOut1(struct libalias * la,struct ip * pip,int create)478effc8e57SLutz Donnerhacke IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
479effc8e57SLutz Donnerhacke {
480ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
4813b160b8bSBrian Somers struct icmp *ic;
4823b160b8bSBrian Somers
483ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
4849fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
4853b160b8bSBrian Somers
4863b160b8bSBrian Somers /* Save overwritten data for when echo packet returns */
487e7581f0fSPoul-Henning Kamp lnk = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create);
488ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
4893b160b8bSBrian Somers u_short alias_id;
4903b160b8bSBrian Somers int accumulate;
4913b160b8bSBrian Somers
492ed01a582SDag-Erling Smørgrav alias_id = GetAliasPort(lnk);
4933b160b8bSBrian Somers
4943b160b8bSBrian Somers /* Since data field is being modified, adjust ICMP checksum */
4953b160b8bSBrian Somers accumulate = ic->icmp_id;
4963b160b8bSBrian Somers accumulate -= alias_id;
49771593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
4983b160b8bSBrian Somers
4993b160b8bSBrian Somers /* Alias sequence number */
5003b160b8bSBrian Somers ic->icmp_id = alias_id;
5013b160b8bSBrian Somers
5023b160b8bSBrian Somers /* Change source address */
5033b160b8bSBrian Somers {
5043b160b8bSBrian Somers struct in_addr alias_address;
5053b160b8bSBrian Somers
506ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
5073b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
5082871c501SDag-Erling Smørgrav &alias_address, &pip->ip_src, 2);
5093b160b8bSBrian Somers pip->ip_src = alias_address;
5103b160b8bSBrian Somers }
5113b160b8bSBrian Somers
5123b160b8bSBrian Somers return (PKT_ALIAS_OK);
5133b160b8bSBrian Somers }
5143b160b8bSBrian Somers return (PKT_ALIAS_IGNORED);
5153b160b8bSBrian Somers }
5163b160b8bSBrian Somers
5173b160b8bSBrian Somers /*
5183b160b8bSBrian Somers Alias outgoing ICMP error messages containing
5193b160b8bSBrian Somers IP header and first 64 bits of datagram.
5203b160b8bSBrian Somers */
521effc8e57SLutz Donnerhacke static int
IcmpAliasOut2(struct libalias * la,struct ip * pip)522effc8e57SLutz Donnerhacke IcmpAliasOut2(struct libalias *la, struct ip *pip)
523effc8e57SLutz Donnerhacke {
5243b160b8bSBrian Somers struct ip *ip;
525680c8244SRuslan Ermilov struct icmp *ic, *ic2;
526680c8244SRuslan Ermilov struct udphdr *ud;
527680c8244SRuslan Ermilov struct tcphdr *tc;
528ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
5293b160b8bSBrian Somers
530ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
5319fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
532305d1069SRuslan Ermilov ip = &ic->icmp_ip;
5333b160b8bSBrian Somers
5349fa0fd26SDag-Erling Smørgrav ud = (struct udphdr *)ip_next(ip);
5359fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(ip);
5369fa0fd26SDag-Erling Smørgrav ic2 = (struct icmp *)ip_next(ip);
5373b160b8bSBrian Somers
538680c8244SRuslan Ermilov if (ip->ip_p == IPPROTO_UDP)
539ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
540680c8244SRuslan Ermilov ud->uh_dport, ud->uh_sport,
541642cd09fSRuslan Ermilov IPPROTO_UDP, 0);
542680c8244SRuslan Ermilov else if (ip->ip_p == IPPROTO_TCP)
543ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
544680c8244SRuslan Ermilov tc->th_dport, tc->th_sport,
545642cd09fSRuslan Ermilov IPPROTO_TCP, 0);
546680c8244SRuslan Ermilov else if (ip->ip_p == IPPROTO_ICMP) {
547680c8244SRuslan Ermilov if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
548ed01a582SDag-Erling Smørgrav lnk = FindIcmpOut(la, ip->ip_dst, ip->ip_src, ic2->icmp_id, 0);
549680c8244SRuslan Ermilov else
550ed01a582SDag-Erling Smørgrav lnk = NULL;
551680c8244SRuslan Ermilov } else
552ed01a582SDag-Erling Smørgrav lnk = NULL;
5533b160b8bSBrian Somers
554ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
555f0f93429SDag-Erling Smørgrav if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
556680c8244SRuslan Ermilov int accumulate;
557680c8244SRuslan Ermilov struct in_addr alias_address;
558680c8244SRuslan Ermilov u_short alias_port;
559680c8244SRuslan Ermilov
560ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
561ed01a582SDag-Erling Smørgrav alias_port = GetAliasPort(lnk);
562680c8244SRuslan Ermilov
563680c8244SRuslan Ermilov /* Adjust ICMP checksum */
5642871c501SDag-Erling Smørgrav accumulate = twowords(&ip->ip_dst);
5652871c501SDag-Erling Smørgrav accumulate -= twowords(&alias_address);
566680c8244SRuslan Ermilov accumulate += ud->uh_dport;
567680c8244SRuslan Ermilov accumulate -= alias_port;
56871593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
569680c8244SRuslan Ermilov
570816fa7feSRuslan Ermilov /*
571816fa7feSRuslan Ermilov * Alias address in IP header if it comes from the host
572816fa7feSRuslan Ermilov * the original TCP/UDP packet was destined for.
573816fa7feSRuslan Ermilov */
574816fa7feSRuslan Ermilov if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
5753b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
5762871c501SDag-Erling Smørgrav &alias_address, &pip->ip_src, 2);
577680c8244SRuslan Ermilov pip->ip_src = alias_address;
578816fa7feSRuslan Ermilov }
579680c8244SRuslan Ermilov /* Alias address and port number of original IP packet
580effc8e57SLutz Donnerhacke * fragment contained in ICMP data section */
581680c8244SRuslan Ermilov ip->ip_dst = alias_address;
582680c8244SRuslan Ermilov ud->uh_dport = alias_port;
583f0f93429SDag-Erling Smørgrav } else if (ip->ip_p == IPPROTO_ICMP) {
584680c8244SRuslan Ermilov int accumulate;
585680c8244SRuslan Ermilov struct in_addr alias_address;
586680c8244SRuslan Ermilov u_short alias_id;
587680c8244SRuslan Ermilov
588ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
589ed01a582SDag-Erling Smørgrav alias_id = GetAliasPort(lnk);
590680c8244SRuslan Ermilov
591680c8244SRuslan Ermilov /* Adjust ICMP checksum */
5922871c501SDag-Erling Smørgrav accumulate = twowords(&ip->ip_dst);
5932871c501SDag-Erling Smørgrav accumulate -= twowords(&alias_address);
594680c8244SRuslan Ermilov accumulate += ic2->icmp_id;
595680c8244SRuslan Ermilov accumulate -= alias_id;
59671593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
597680c8244SRuslan Ermilov
598816fa7feSRuslan Ermilov /*
599816fa7feSRuslan Ermilov * Alias address in IP header if it comes from the host
600816fa7feSRuslan Ermilov * the original ICMP message was destined for.
601816fa7feSRuslan Ermilov */
602816fa7feSRuslan Ermilov if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
603680c8244SRuslan Ermilov DifferentialChecksum(&pip->ip_sum,
6042871c501SDag-Erling Smørgrav &alias_address, &pip->ip_src, 2);
605680c8244SRuslan Ermilov pip->ip_src = alias_address;
606816fa7feSRuslan Ermilov }
607effc8e57SLutz Donnerhacke /* Alias address of original IP packet and
608effc8e57SLutz Donnerhacke * sequence number of embedded ICMP datagram */
609680c8244SRuslan Ermilov ip->ip_dst = alias_address;
610680c8244SRuslan Ermilov ic2->icmp_id = alias_id;
611680c8244SRuslan Ermilov }
612680c8244SRuslan Ermilov return (PKT_ALIAS_OK);
613680c8244SRuslan Ermilov }
614680c8244SRuslan Ermilov return (PKT_ALIAS_IGNORED);
6153b160b8bSBrian Somers }
6163b160b8bSBrian Somers
6173b160b8bSBrian Somers static int
IcmpAliasOut(struct libalias * la,struct ip * pip,int create)618e6bbb691SPoul-Henning Kamp IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
6193b160b8bSBrian Somers {
6203b160b8bSBrian Somers int iresult;
6213b160b8bSBrian Somers struct icmp *ic;
6223b160b8bSBrian Somers
623ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
624ed01a582SDag-Erling Smørgrav (void)create;
625ed01a582SDag-Erling Smørgrav
6267d96f4efSBrian Somers /* Return if proxy-only mode is enabled */
6275e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
628ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
6297d96f4efSBrian Somers
6309fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
6313b160b8bSBrian Somers
6323b160b8bSBrian Somers iresult = PKT_ALIAS_IGNORED;
633f0f93429SDag-Erling Smørgrav switch (ic->icmp_type) {
6343b160b8bSBrian Somers case ICMP_ECHO:
6353b160b8bSBrian Somers case ICMP_TSTAMP:
636f0f93429SDag-Erling Smørgrav if (ic->icmp_code == 0) {
637e7581f0fSPoul-Henning Kamp iresult = IcmpAliasOut1(la, pip, create);
6383b160b8bSBrian Somers }
6393b160b8bSBrian Somers break;
6403b160b8bSBrian Somers case ICMP_UNREACH:
6413b160b8bSBrian Somers case ICMP_SOURCEQUENCH:
6423b160b8bSBrian Somers case ICMP_TIMXCEED:
6433b160b8bSBrian Somers case ICMP_PARAMPROB:
6445e289f9eSPoul-Henning Kamp iresult = IcmpAliasOut2(la, pip);
6453b160b8bSBrian Somers break;
6463b160b8bSBrian Somers case ICMP_ECHOREPLY:
6473b160b8bSBrian Somers case ICMP_TSTAMPREPLY:
648e7581f0fSPoul-Henning Kamp iresult = IcmpAliasOut1(la, pip, create);
6493b160b8bSBrian Somers }
6503b160b8bSBrian Somers return (iresult);
6513b160b8bSBrian Somers }
6523b160b8bSBrian Somers
6537d96f4efSBrian Somers /*
65480607605SRuslan Ermilov Handle incoming IP packets. The
6557d96f4efSBrian Somers only thing which is done in this case is to alias
6567d96f4efSBrian Somers the dest IP address of the packet to our inside
6577d96f4efSBrian Somers machine.
6587d96f4efSBrian Somers */
659effc8e57SLutz Donnerhacke static int
ProtoAliasIn(struct libalias * la,struct in_addr ip_src,struct ip * pip,u_char ip_p,u_short * ip_sum)660effc8e57SLutz Donnerhacke ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
661effc8e57SLutz Donnerhacke struct ip *pip, u_char ip_p, u_short *ip_sum)
662effc8e57SLutz Donnerhacke {
663ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
6647d96f4efSBrian Somers
665ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
666483d2f22SRuslan Ermilov /* Return if proxy-only mode is enabled */
6675e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
668ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
669483d2f22SRuslan Ermilov
670bc596e56SAlex Richardson lnk = FindProtoIn(la, ip_src, pip->ip_dst, ip_p);
671ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
672483d2f22SRuslan Ermilov struct in_addr original_address;
6737d96f4efSBrian Somers
674ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
675483d2f22SRuslan Ermilov
676483d2f22SRuslan Ermilov /* Restore original IP address */
677ab0fcfd0SPaolo Pisati DifferentialChecksum(ip_sum,
678bc596e56SAlex Richardson &original_address, &pip->ip_dst, 2);
679bc596e56SAlex Richardson pip->ip_dst = original_address;
6807d96f4efSBrian Somers
681483d2f22SRuslan Ermilov return (PKT_ALIAS_OK);
682483d2f22SRuslan Ermilov }
683483d2f22SRuslan Ermilov return (PKT_ALIAS_IGNORED);
6847d96f4efSBrian Somers }
6857d96f4efSBrian Somers
6867d96f4efSBrian Somers /*
68780607605SRuslan Ermilov Handle outgoing IP packets. The
6887d96f4efSBrian Somers only thing which is done in this case is to alias
6897d96f4efSBrian Somers the source IP address of the packet.
6907d96f4efSBrian Somers */
691effc8e57SLutz Donnerhacke static int
ProtoAliasOut(struct libalias * la,struct ip * pip,struct in_addr ip_dst,u_char ip_p,u_short * ip_sum,int create)692effc8e57SLutz Donnerhacke ProtoAliasOut(struct libalias *la, struct ip *pip,
693effc8e57SLutz Donnerhacke struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
694effc8e57SLutz Donnerhacke {
695ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
696ed01a582SDag-Erling Smørgrav
697ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
6987d96f4efSBrian Somers
699483d2f22SRuslan Ermilov /* Return if proxy-only mode is enabled */
7005e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
701ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
702483d2f22SRuslan Ermilov
7031a356b8bSEugene Grosbein if (!create)
7041a356b8bSEugene Grosbein return (PKT_ALIAS_IGNORED);
7051a356b8bSEugene Grosbein
706bc596e56SAlex Richardson lnk = FindProtoOut(la, pip->ip_src, ip_dst, ip_p);
707ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
708483d2f22SRuslan Ermilov struct in_addr alias_address;
7097d96f4efSBrian Somers
710ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
711483d2f22SRuslan Ermilov
712483d2f22SRuslan Ermilov /* Change source address */
713ab0fcfd0SPaolo Pisati DifferentialChecksum(ip_sum,
714bc596e56SAlex Richardson &alias_address, &pip->ip_src, 2);
715bc596e56SAlex Richardson pip->ip_src = alias_address;
7167d96f4efSBrian Somers
717483d2f22SRuslan Ermilov return (PKT_ALIAS_OK);
718483d2f22SRuslan Ermilov }
719483d2f22SRuslan Ermilov return (PKT_ALIAS_IGNORED);
7207d96f4efSBrian Somers }
7217d96f4efSBrian Somers
722461e6f23SMaxim Sobolev #define MF_ISSET(_pip) (ntohs((_pip)->ip_off) & IP_MF)
723461e6f23SMaxim Sobolev #define FRAG_NO_HDR(_pip) (ntohs((_pip)->ip_off) & IP_OFFMASK)
724461e6f23SMaxim Sobolev
725461e6f23SMaxim Sobolev static struct udphdr *
ValidateUdpLength(struct ip * pip)726461e6f23SMaxim Sobolev ValidateUdpLength(struct ip *pip)
727461e6f23SMaxim Sobolev {
728461e6f23SMaxim Sobolev struct udphdr *ud;
729461e6f23SMaxim Sobolev size_t dlen;
730461e6f23SMaxim Sobolev
731461e6f23SMaxim Sobolev #ifdef _KERNEL
732461e6f23SMaxim Sobolev KASSERT(!FRAG_NO_HDR(pip), ("header-less fragment isn't expected here"));
733461e6f23SMaxim Sobolev #endif
734461e6f23SMaxim Sobolev dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
735461e6f23SMaxim Sobolev if (dlen < sizeof(struct udphdr))
736461e6f23SMaxim Sobolev return (NULL);
737461e6f23SMaxim Sobolev ud = (struct udphdr *)ip_next(pip);
738461e6f23SMaxim Sobolev if (!MF_ISSET(pip) && dlen < ntohs(ud->uh_ulen))
739461e6f23SMaxim Sobolev return (NULL);
740461e6f23SMaxim Sobolev return (ud);
741461e6f23SMaxim Sobolev }
742461e6f23SMaxim Sobolev
74355a39fc5SRuslan Ermilov static int
UdpAliasIn(struct libalias * la,struct ip * pip)7445e289f9eSPoul-Henning Kamp UdpAliasIn(struct libalias *la, struct ip *pip)
7453b160b8bSBrian Somers {
7463b160b8bSBrian Somers struct udphdr *ud;
747ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
7483b160b8bSBrian Somers
749ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
7507d96f4efSBrian Somers
751461e6f23SMaxim Sobolev ud = ValidateUdpLength(pip);
752461e6f23SMaxim Sobolev if (ud == NULL)
7536461c83eSEd Maste return (PKT_ALIAS_IGNORED);
7543b160b8bSBrian Somers
755ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
7563b160b8bSBrian Somers ud->uh_sport, ud->uh_dport,
757ea29dd92SAlexander Motin IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
758ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
7593b160b8bSBrian Somers struct in_addr alias_address;
7603b160b8bSBrian Somers struct in_addr original_address;
761ea29dd92SAlexander Motin struct in_addr proxy_address;
7623b160b8bSBrian Somers u_short alias_port;
763ea29dd92SAlexander Motin u_short proxy_port;
7643b160b8bSBrian Somers int accumulate;
765ea80b0acSPaolo Pisati int error;
766be4f3cd0SPaolo Pisati struct alias_data ad = {
767be4f3cd0SPaolo Pisati .lnk = lnk,
768be4f3cd0SPaolo Pisati .oaddr = &original_address,
769be4f3cd0SPaolo Pisati .aaddr = &alias_address,
770be4f3cd0SPaolo Pisati .aport = &alias_port,
771be4f3cd0SPaolo Pisati .sport = &ud->uh_sport,
772be4f3cd0SPaolo Pisati .dport = &ud->uh_dport,
773be4f3cd0SPaolo Pisati .maxpktsize = 0
774be4f3cd0SPaolo Pisati };
7753b160b8bSBrian Somers
776ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
777ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
778ea29dd92SAlexander Motin proxy_address = GetProxyAddress(lnk);
7793b160b8bSBrian Somers alias_port = ud->uh_dport;
780ed01a582SDag-Erling Smørgrav ud->uh_dport = GetOriginalPort(lnk);
781ea29dd92SAlexander Motin proxy_port = GetProxyPort(lnk);
7823b160b8bSBrian Somers
783be4f3cd0SPaolo Pisati /* Walk out chain. */
784be4f3cd0SPaolo Pisati error = find_handler(IN, UDP, la, pip, &ad);
78550d25ddaSPaolo Pisati /* If we cannot figure out the packet, ignore it. */
78650d25ddaSPaolo Pisati if (error < 0)
78750d25ddaSPaolo Pisati return (PKT_ALIAS_IGNORED);
7880579bd71SBrian Somers
789effc8e57SLutz Donnerhacke /* If UDP checksum is not zero, then adjust since
790effc8e57SLutz Donnerhacke * destination port is being unaliased and
791effc8e57SLutz Donnerhacke * destination address is being altered. */
792f0f93429SDag-Erling Smørgrav if (ud->uh_sum != 0) {
7933b160b8bSBrian Somers accumulate = alias_port;
7943b160b8bSBrian Somers accumulate -= ud->uh_dport;
7952871c501SDag-Erling Smørgrav accumulate += twowords(&alias_address);
7962871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
797ea29dd92SAlexander Motin
798effc8e57SLutz Donnerhacke /* If this is a proxy packet, modify checksum
799effc8e57SLutz Donnerhacke * because of source change.*/
800ea29dd92SAlexander Motin if (proxy_port != 0) {
801ea29dd92SAlexander Motin accumulate += ud->uh_sport;
802ea29dd92SAlexander Motin accumulate -= proxy_port;
803ea29dd92SAlexander Motin }
804ea29dd92SAlexander Motin
805ea29dd92SAlexander Motin if (proxy_address.s_addr != 0) {
806ea29dd92SAlexander Motin accumulate += twowords(&pip->ip_src);
807ea29dd92SAlexander Motin accumulate -= twowords(&proxy_address);
808ea29dd92SAlexander Motin }
809ea29dd92SAlexander Motin
81071593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ud->uh_sum);
8113b160b8bSBrian Somers }
812effc8e57SLutz Donnerhacke
813ea29dd92SAlexander Motin /* XXX: Could the two if's below be concatenated to one ? */
814ea29dd92SAlexander Motin /* Restore source port and/or address in case of proxying*/
815ea29dd92SAlexander Motin if (proxy_port != 0)
816ea29dd92SAlexander Motin ud->uh_sport = proxy_port;
817ea29dd92SAlexander Motin
818ea29dd92SAlexander Motin if (proxy_address.s_addr != 0) {
819ea29dd92SAlexander Motin DifferentialChecksum(&pip->ip_sum,
820ea29dd92SAlexander Motin &proxy_address, &pip->ip_src, 2);
821ea29dd92SAlexander Motin pip->ip_src = proxy_address;
822ea29dd92SAlexander Motin }
823ea29dd92SAlexander Motin
8243b160b8bSBrian Somers /* Restore original IP address */
8253b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
8262871c501SDag-Erling Smørgrav &original_address, &pip->ip_dst, 2);
8273b160b8bSBrian Somers pip->ip_dst = original_address;
828374fad8bSMatthew Dillon
8293b160b8bSBrian Somers return (PKT_ALIAS_OK);
8303b160b8bSBrian Somers }
8313b160b8bSBrian Somers return (PKT_ALIAS_IGNORED);
8323b160b8bSBrian Somers }
8333b160b8bSBrian Somers
8343b160b8bSBrian Somers static int
UdpAliasOut(struct libalias * la,struct ip * pip,int maxpacketsize,int create)835ea29dd92SAlexander Motin UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
8363b160b8bSBrian Somers {
8373b160b8bSBrian Somers struct udphdr *ud;
838ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
839ea29dd92SAlexander Motin struct in_addr dest_address;
840ea29dd92SAlexander Motin struct in_addr proxy_server_address;
841ea29dd92SAlexander Motin u_short dest_port;
842ea29dd92SAlexander Motin u_short proxy_server_port;
843ea29dd92SAlexander Motin int proxy_type;
8443b160b8bSBrian Somers
845ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
846ea29dd92SAlexander Motin
847461e6f23SMaxim Sobolev ud = ValidateUdpLength(pip);
848461e6f23SMaxim Sobolev if (ud == NULL)
849461e6f23SMaxim Sobolev return (PKT_ALIAS_IGNORED);
850461e6f23SMaxim Sobolev
851ea29dd92SAlexander Motin /* Return if proxy-only mode is enabled and not proxyrule found.*/
852effc8e57SLutz Donnerhacke proxy_type = ProxyCheck(la, &proxy_server_address, &proxy_server_port,
853effc8e57SLutz Donnerhacke pip->ip_src, pip->ip_dst, ud->uh_dport, pip->ip_p);
854ea29dd92SAlexander Motin if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
855ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
8567d96f4efSBrian Somers
857ea29dd92SAlexander Motin /* If this is a transparent proxy, save original destination,
858ea29dd92SAlexander Motin * then alter the destination and adjust checksums */
859ea29dd92SAlexander Motin dest_port = ud->uh_dport;
860ea29dd92SAlexander Motin dest_address = pip->ip_dst;
8613b160b8bSBrian Somers
862ea29dd92SAlexander Motin if (proxy_type != 0) {
863ea29dd92SAlexander Motin int accumulate;
864ea29dd92SAlexander Motin
865ea29dd92SAlexander Motin accumulate = twowords(&pip->ip_dst);
866ea29dd92SAlexander Motin accumulate -= twowords(&proxy_server_address);
867ea29dd92SAlexander Motin
868ea29dd92SAlexander Motin ADJUST_CHECKSUM(accumulate, pip->ip_sum);
869ea29dd92SAlexander Motin
870ea29dd92SAlexander Motin if (ud->uh_sum != 0) {
871ea29dd92SAlexander Motin accumulate = twowords(&pip->ip_dst);
872ea29dd92SAlexander Motin accumulate -= twowords(&proxy_server_address);
873ea29dd92SAlexander Motin accumulate += ud->uh_dport;
874ea29dd92SAlexander Motin accumulate -= proxy_server_port;
875ea29dd92SAlexander Motin ADJUST_CHECKSUM(accumulate, ud->uh_sum);
876ea29dd92SAlexander Motin }
877ea29dd92SAlexander Motin pip->ip_dst = proxy_server_address;
878ea29dd92SAlexander Motin ud->uh_dport = proxy_server_port;
879ea29dd92SAlexander Motin }
880ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
8813b160b8bSBrian Somers ud->uh_sport, ud->uh_dport,
882e6bbb691SPoul-Henning Kamp IPPROTO_UDP, create);
883ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
8843b160b8bSBrian Somers u_short alias_port;
8853b160b8bSBrian Somers struct in_addr alias_address;
886be4f3cd0SPaolo Pisati struct alias_data ad = {
887be4f3cd0SPaolo Pisati .lnk = lnk,
888be4f3cd0SPaolo Pisati .oaddr = NULL,
889be4f3cd0SPaolo Pisati .aaddr = &alias_address,
890be4f3cd0SPaolo Pisati .aport = &alias_port,
891be4f3cd0SPaolo Pisati .sport = &ud->uh_sport,
892be4f3cd0SPaolo Pisati .dport = &ud->uh_dport,
893be4f3cd0SPaolo Pisati .maxpktsize = 0
894be4f3cd0SPaolo Pisati };
8953b160b8bSBrian Somers
896ea29dd92SAlexander Motin /* Save original destination address, if this is a proxy packet.
897ea29dd92SAlexander Motin * Also modify packet to include destination encoding. This may
898ea29dd92SAlexander Motin * change the size of IP header. */
899ea29dd92SAlexander Motin if (proxy_type != 0) {
900ea29dd92SAlexander Motin SetProxyPort(lnk, dest_port);
901ea29dd92SAlexander Motin SetProxyAddress(lnk, dest_address);
902ea29dd92SAlexander Motin ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
903ea29dd92SAlexander Motin ud = (struct udphdr *)ip_next(pip);
904ea29dd92SAlexander Motin }
905ea29dd92SAlexander Motin
906ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
907ed01a582SDag-Erling Smørgrav alias_port = GetAliasPort(lnk);
9083b160b8bSBrian Somers
909be4f3cd0SPaolo Pisati /* Walk out chain. */
9106454d0c8SJohn Baldwin find_handler(OUT, UDP, la, pip, &ad);
911fb9cd36dSAtsushi Murai
9123b160b8bSBrian Somers /* If UDP checksum is not zero, adjust since source port is */
9133b160b8bSBrian Somers /* being aliased and source address is being altered */
914f0f93429SDag-Erling Smørgrav if (ud->uh_sum != 0) {
9153b160b8bSBrian Somers int accumulate;
9163b160b8bSBrian Somers
9173b160b8bSBrian Somers accumulate = ud->uh_sport;
9183b160b8bSBrian Somers accumulate -= alias_port;
9192871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_src);
9202871c501SDag-Erling Smørgrav accumulate -= twowords(&alias_address);
92171593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ud->uh_sum);
9223b160b8bSBrian Somers }
923fb9cd36dSAtsushi Murai /* Put alias port in UDP header */
9243b160b8bSBrian Somers ud->uh_sport = alias_port;
9253b160b8bSBrian Somers
9263b160b8bSBrian Somers /* Change source address */
9273b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
9282871c501SDag-Erling Smørgrav &alias_address, &pip->ip_src, 2);
9293b160b8bSBrian Somers pip->ip_src = alias_address;
9303b160b8bSBrian Somers
9313b160b8bSBrian Somers return (PKT_ALIAS_OK);
9323b160b8bSBrian Somers }
9333b160b8bSBrian Somers return (PKT_ALIAS_IGNORED);
9343b160b8bSBrian Somers }
9353b160b8bSBrian Somers
9363b160b8bSBrian Somers static int
TcpAliasIn(struct libalias * la,struct ip * pip)9375e289f9eSPoul-Henning Kamp TcpAliasIn(struct libalias *la, struct ip *pip)
9383b160b8bSBrian Somers {
9393b160b8bSBrian Somers struct tcphdr *tc;
940ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
941be597269SAlex Richardson size_t dlen;
9423b160b8bSBrian Somers
943ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
9446461c83eSEd Maste
9456461c83eSEd Maste dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
9466461c83eSEd Maste if (dlen < sizeof(struct tcphdr))
9476461c83eSEd Maste return (PKT_ALIAS_IGNORED);
9489fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
9493b160b8bSBrian Somers
950ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
9513b160b8bSBrian Somers tc->th_sport, tc->th_dport,
952642cd09fSRuslan Ermilov IPPROTO_TCP,
9535e289f9eSPoul-Henning Kamp !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY));
954ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
9553b160b8bSBrian Somers struct in_addr alias_address;
9563b160b8bSBrian Somers struct in_addr original_address;
9577d96f4efSBrian Somers struct in_addr proxy_address;
9583b160b8bSBrian Somers u_short alias_port;
9597d96f4efSBrian Somers u_short proxy_port;
9606454d0c8SJohn Baldwin int accumulate;
9613b160b8bSBrian Somers
962be4f3cd0SPaolo Pisati /*
963be4f3cd0SPaolo Pisati * The init of MANY vars is a bit below, but aliashandlepptpin
964be4f3cd0SPaolo Pisati * seems to need the destination port that came within the
965be4f3cd0SPaolo Pisati * packet and not the original one looks below [*].
966be4f3cd0SPaolo Pisati */
967be4f3cd0SPaolo Pisati
968be4f3cd0SPaolo Pisati struct alias_data ad = {
969be4f3cd0SPaolo Pisati .lnk = lnk,
970be4f3cd0SPaolo Pisati .oaddr = NULL,
971be4f3cd0SPaolo Pisati .aaddr = NULL,
972be4f3cd0SPaolo Pisati .aport = NULL,
973be4f3cd0SPaolo Pisati .sport = &tc->th_sport,
974be4f3cd0SPaolo Pisati .dport = &tc->th_dport,
975be4f3cd0SPaolo Pisati .maxpktsize = 0
976be4f3cd0SPaolo Pisati };
977be4f3cd0SPaolo Pisati
978be4f3cd0SPaolo Pisati /* Walk out chain. */
9796454d0c8SJohn Baldwin find_handler(IN, TCP, la, pip, &ad);
98055a39fc5SRuslan Ermilov
981ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
982ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
983ed01a582SDag-Erling Smørgrav proxy_address = GetProxyAddress(lnk);
9843b160b8bSBrian Somers alias_port = tc->th_dport;
985ed01a582SDag-Erling Smørgrav tc->th_dport = GetOriginalPort(lnk);
986ed01a582SDag-Erling Smørgrav proxy_port = GetProxyPort(lnk);
9873b160b8bSBrian Somers
988be4f3cd0SPaolo Pisati /*
989be4f3cd0SPaolo Pisati * Look above, if anyone is going to add find_handler AFTER
990be4f3cd0SPaolo Pisati * this aliashandlepptpin/point, please redo alias_data too.
991be4f3cd0SPaolo Pisati * Uncommenting the piece here below should be enough.
992be4f3cd0SPaolo Pisati */
993be4f3cd0SPaolo Pisati #if 0
994be4f3cd0SPaolo Pisati struct alias_data ad = {
995be4f3cd0SPaolo Pisati .lnk = lnk,
996be4f3cd0SPaolo Pisati .oaddr = &original_address,
997be4f3cd0SPaolo Pisati .aaddr = &alias_address,
998be4f3cd0SPaolo Pisati .aport = &alias_port,
999be4f3cd0SPaolo Pisati .sport = &ud->uh_sport,
1000be4f3cd0SPaolo Pisati .dport = &ud->uh_dport,
1001be4f3cd0SPaolo Pisati .maxpktsize = 0
1002be4f3cd0SPaolo Pisati };
1003be4f3cd0SPaolo Pisati
1004be4f3cd0SPaolo Pisati /* Walk out chain. */
1005be4f3cd0SPaolo Pisati error = find_handler(la, pip, &ad);
1006be4f3cd0SPaolo Pisati if (error == EHDNOF)
1007be4f3cd0SPaolo Pisati printf("Protocol handler not found\n");
1008be4f3cd0SPaolo Pisati #endif
1009be4f3cd0SPaolo Pisati
1010effc8e57SLutz Donnerhacke /* Adjust TCP checksum since destination port is being
1011effc8e57SLutz Donnerhacke * unaliased and destination port is being altered. */
10123b160b8bSBrian Somers accumulate = alias_port;
10133b160b8bSBrian Somers accumulate -= tc->th_dport;
10142871c501SDag-Erling Smørgrav accumulate += twowords(&alias_address);
10152871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
10163b160b8bSBrian Somers
1017effc8e57SLutz Donnerhacke /* If this is a proxy, then modify the TCP source port
1018effc8e57SLutz Donnerhacke * and checksum accumulation */
1019f0f93429SDag-Erling Smørgrav if (proxy_port != 0) {
10207d96f4efSBrian Somers accumulate += tc->th_sport;
10217d96f4efSBrian Somers tc->th_sport = proxy_port;
10227d96f4efSBrian Somers accumulate -= tc->th_sport;
10232871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_src);
10242871c501SDag-Erling Smørgrav accumulate -= twowords(&proxy_address);
10257d96f4efSBrian Somers }
1026483d2f22SRuslan Ermilov /* See if ACK number needs to be modified */
1027ed01a582SDag-Erling Smørgrav if (GetAckModified(lnk) == 1) {
10283b160b8bSBrian Somers int delta;
10293b160b8bSBrian Somers
10304741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
10314741f3a1SPaolo Pisati delta = GetDeltaAckIn(tc->th_ack, lnk);
1032f0f93429SDag-Erling Smørgrav if (delta != 0) {
10332871c501SDag-Erling Smørgrav accumulate += twowords(&tc->th_ack);
10343b160b8bSBrian Somers tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
10352871c501SDag-Erling Smørgrav accumulate -= twowords(&tc->th_ack);
10363b160b8bSBrian Somers }
10373b160b8bSBrian Somers }
10383b160b8bSBrian Somers ADJUST_CHECKSUM(accumulate, tc->th_sum);
10393b160b8bSBrian Somers
10403b160b8bSBrian Somers /* Restore original IP address */
10412871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_dst);
1042ab39bc9aSDaniel Eischen pip->ip_dst = original_address;
10432871c501SDag-Erling Smørgrav accumulate -= twowords(&pip->ip_dst);
10447d96f4efSBrian Somers
1045effc8e57SLutz Donnerhacke /* If this is a transparent proxy packet,
1046effc8e57SLutz Donnerhacke * then modify the source address */
1047f0f93429SDag-Erling Smørgrav if (proxy_address.s_addr != 0) {
10482871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_src);
10497d96f4efSBrian Somers pip->ip_src = proxy_address;
10502871c501SDag-Erling Smørgrav accumulate -= twowords(&pip->ip_src);
10517d96f4efSBrian Somers }
10527d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum);
10533b160b8bSBrian Somers
10543b160b8bSBrian Somers /* Monitor TCP connection state */
10554741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
1056*0fc7bdc9SRichard Scheffenegger TcpMonitorIn(__tcp_get_flags(tc), lnk);
10573b160b8bSBrian Somers
10583b160b8bSBrian Somers return (PKT_ALIAS_OK);
10593b160b8bSBrian Somers }
10603b160b8bSBrian Somers return (PKT_ALIAS_IGNORED);
10613b160b8bSBrian Somers }
10623b160b8bSBrian Somers
10633b160b8bSBrian Somers static int
TcpAliasOut(struct libalias * la,struct ip * pip,int maxpacketsize,int create)1064e6bbb691SPoul-Henning Kamp TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
10653b160b8bSBrian Somers {
10666454d0c8SJohn Baldwin int proxy_type;
10677d96f4efSBrian Somers u_short dest_port;
10687d96f4efSBrian Somers u_short proxy_server_port;
1069be597269SAlex Richardson size_t dlen;
10707d96f4efSBrian Somers struct in_addr dest_address;
10717d96f4efSBrian Somers struct in_addr proxy_server_address;
10723b160b8bSBrian Somers struct tcphdr *tc;
1073ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
10743b160b8bSBrian Somers
1075ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
10766461c83eSEd Maste
10776461c83eSEd Maste dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
10786461c83eSEd Maste if (dlen < sizeof(struct tcphdr))
10796461c83eSEd Maste return (PKT_ALIAS_IGNORED);
10809fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
10813b160b8bSBrian Somers
1082dca9c930SPoul-Henning Kamp if (create)
10834741f3a1SPaolo Pisati proxy_type = ProxyCheck(la, &proxy_server_address,
10844741f3a1SPaolo Pisati &proxy_server_port, pip->ip_src, pip->ip_dst,
10854741f3a1SPaolo Pisati tc->th_dport, pip->ip_p);
1086dca9c930SPoul-Henning Kamp else
1087dca9c930SPoul-Henning Kamp proxy_type = 0;
10887d96f4efSBrian Somers
10895e289f9eSPoul-Henning Kamp if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1090ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
10917d96f4efSBrian Somers
10927d96f4efSBrian Somers /* If this is a transparent proxy, save original destination,
1093effc8e57SLutz Donnerhacke * then alter the destination and adjust checksums */
10947d96f4efSBrian Somers dest_port = tc->th_dport;
10957d96f4efSBrian Somers dest_address = pip->ip_dst;
1096f0f93429SDag-Erling Smørgrav if (proxy_type != 0) {
10977d96f4efSBrian Somers int accumulate;
10987d96f4efSBrian Somers
10997d96f4efSBrian Somers accumulate = tc->th_dport;
11007d96f4efSBrian Somers tc->th_dport = proxy_server_port;
11017d96f4efSBrian Somers accumulate -= tc->th_dport;
11022871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_dst);
11032871c501SDag-Erling Smørgrav accumulate -= twowords(&proxy_server_address);
11047d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, tc->th_sum);
11057d96f4efSBrian Somers
11062871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_dst);
11077d96f4efSBrian Somers pip->ip_dst = proxy_server_address;
11082871c501SDag-Erling Smørgrav accumulate -= twowords(&pip->ip_dst);
11097d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum);
11107d96f4efSBrian Somers }
1111ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
11123b160b8bSBrian Somers tc->th_sport, tc->th_dport,
1113e6bbb691SPoul-Henning Kamp IPPROTO_TCP, create);
1114ed01a582SDag-Erling Smørgrav if (lnk == NULL)
1115e6bbb691SPoul-Henning Kamp return (PKT_ALIAS_IGNORED);
1116ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
11173b160b8bSBrian Somers u_short alias_port;
11187d96f4efSBrian Somers struct in_addr alias_address;
11193b160b8bSBrian Somers int accumulate;
1120be4f3cd0SPaolo Pisati struct alias_data ad = {
1121be4f3cd0SPaolo Pisati .lnk = lnk,
1122be4f3cd0SPaolo Pisati .oaddr = NULL,
1123be4f3cd0SPaolo Pisati .aaddr = &alias_address,
1124be4f3cd0SPaolo Pisati .aport = &alias_port,
1125be4f3cd0SPaolo Pisati .sport = &tc->th_sport,
1126be4f3cd0SPaolo Pisati .dport = &tc->th_dport,
1127be4f3cd0SPaolo Pisati .maxpktsize = maxpacketsize
1128be4f3cd0SPaolo Pisati };
11293b160b8bSBrian Somers
11307d96f4efSBrian Somers /* Save original destination address, if this is a proxy packet.
1131effc8e57SLutz Donnerhacke * Also modify packet to include destination
1132effc8e57SLutz Donnerhacke * encoding. This may change the size of IP header. */
1133f0f93429SDag-Erling Smørgrav if (proxy_type != 0) {
1134ed01a582SDag-Erling Smørgrav SetProxyPort(lnk, dest_port);
1135ed01a582SDag-Erling Smørgrav SetProxyAddress(lnk, dest_address);
1136ed01a582SDag-Erling Smørgrav ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
11379fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
11387d96f4efSBrian Somers }
11397d96f4efSBrian Somers /* Get alias address and port */
1140ed01a582SDag-Erling Smørgrav alias_port = GetAliasPort(lnk);
1141ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
11423b160b8bSBrian Somers
1143483d2f22SRuslan Ermilov /* Monitor TCP connection state */
11444741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
1145*0fc7bdc9SRichard Scheffenegger TcpMonitorOut(__tcp_get_flags(tc), lnk);
11463b160b8bSBrian Somers
1147be4f3cd0SPaolo Pisati /* Walk out chain. */
11486454d0c8SJohn Baldwin find_handler(OUT, TCP, la, pip, &ad);
11493b160b8bSBrian Somers
1150effc8e57SLutz Donnerhacke /* Adjust TCP checksum since source port is being aliased
1151effc8e57SLutz Donnerhacke * and source address is being altered */
11523b160b8bSBrian Somers accumulate = tc->th_sport;
11537d96f4efSBrian Somers tc->th_sport = alias_port;
11547d96f4efSBrian Somers accumulate -= tc->th_sport;
11552871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_src);
11562871c501SDag-Erling Smørgrav accumulate -= twowords(&alias_address);
11573b160b8bSBrian Somers
11583b160b8bSBrian Somers /* Modify sequence number if necessary */
1159ed01a582SDag-Erling Smørgrav if (GetAckModified(lnk) == 1) {
11603b160b8bSBrian Somers int delta;
11613b160b8bSBrian Somers
11624741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
11634741f3a1SPaolo Pisati delta = GetDeltaSeqOut(tc->th_seq, lnk);
1164f0f93429SDag-Erling Smørgrav if (delta != 0) {
11652871c501SDag-Erling Smørgrav accumulate += twowords(&tc->th_seq);
11663b160b8bSBrian Somers tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
11672871c501SDag-Erling Smørgrav accumulate -= twowords(&tc->th_seq);
11683b160b8bSBrian Somers }
11693b160b8bSBrian Somers }
117071593f95SBrian Somers ADJUST_CHECKSUM(accumulate, tc->th_sum);
11713b160b8bSBrian Somers
11723b160b8bSBrian Somers /* Change source address */
11732871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_src);
11743b160b8bSBrian Somers pip->ip_src = alias_address;
11752871c501SDag-Erling Smørgrav accumulate -= twowords(&pip->ip_src);
117671593f95SBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum);
11773b160b8bSBrian Somers
11783b160b8bSBrian Somers return (PKT_ALIAS_OK);
11793b160b8bSBrian Somers }
11803b160b8bSBrian Somers return (PKT_ALIAS_IGNORED);
11813b160b8bSBrian Somers }
11823b160b8bSBrian Somers
11833b160b8bSBrian Somers /* Fragment Handling
11843b160b8bSBrian Somers
11853b160b8bSBrian Somers FragmentIn()
11863b160b8bSBrian Somers FragmentOut()
11873b160b8bSBrian Somers
11883b160b8bSBrian Somers The packet aliasing module has a limited ability for handling IP
11893b160b8bSBrian Somers fragments. If the ICMP, TCP or UDP header is in the first fragment
1190483d2f22SRuslan Ermilov received, then the ID number of the IP packet is saved, and other
11913b160b8bSBrian Somers fragments are identified according to their ID number and IP address
11923b160b8bSBrian Somers they were sent from. Pointers to unresolved fragments can also be
11933b160b8bSBrian Somers saved and recalled when a header fragment is seen.
11943b160b8bSBrian Somers */
11953b160b8bSBrian Somers
11963b160b8bSBrian Somers /* Local prototypes */
1197ab0fcfd0SPaolo Pisati static int FragmentIn(struct libalias *la, struct in_addr ip_src,
1198bc596e56SAlex Richardson struct ip *pip, u_short ip_id, u_short *ip_sum);
1199bc596e56SAlex Richardson static int FragmentOut(struct libalias *, struct ip *pip,
1200ab0fcfd0SPaolo Pisati u_short *ip_sum);
12013b160b8bSBrian Somers
12023b160b8bSBrian Somers static int
FragmentIn(struct libalias * la,struct in_addr ip_src,struct ip * pip,u_short ip_id,u_short * ip_sum)1203bc596e56SAlex Richardson FragmentIn(struct libalias *la, struct in_addr ip_src, struct ip *pip,
1204aac54f0aSAlexander Motin u_short ip_id, u_short *ip_sum)
12053b160b8bSBrian Somers {
1206ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
12073b160b8bSBrian Somers
1208ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
1209bc596e56SAlex Richardson lnk = FindFragmentIn2(la, ip_src, pip->ip_dst, ip_id);
1210ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
12113b160b8bSBrian Somers struct in_addr original_address;
12123b160b8bSBrian Somers
1213ed01a582SDag-Erling Smørgrav GetFragmentAddr(lnk, &original_address);
1214ab0fcfd0SPaolo Pisati DifferentialChecksum(ip_sum,
1215bc596e56SAlex Richardson &original_address, &pip->ip_dst, 2);
1216bc596e56SAlex Richardson pip->ip_dst = original_address;
12173b160b8bSBrian Somers
12183b160b8bSBrian Somers return (PKT_ALIAS_OK);
12193b160b8bSBrian Somers }
12203b160b8bSBrian Somers return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
12213b160b8bSBrian Somers }
12223b160b8bSBrian Somers
12233b160b8bSBrian Somers static int
FragmentOut(struct libalias * la,struct ip * pip,u_short * ip_sum)1224bc596e56SAlex Richardson FragmentOut(struct libalias *la, struct ip *pip, u_short *ip_sum)
12253b160b8bSBrian Somers {
12263b160b8bSBrian Somers struct in_addr alias_address;
12273b160b8bSBrian Somers
1228ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
1229bc596e56SAlex Richardson alias_address = FindAliasAddress(la, pip->ip_src);
1230ab0fcfd0SPaolo Pisati DifferentialChecksum(ip_sum,
1231bc596e56SAlex Richardson &alias_address, &pip->ip_src, 2);
1232bc596e56SAlex Richardson pip->ip_src = alias_address;
12333b160b8bSBrian Somers
12343b160b8bSBrian Somers return (PKT_ALIAS_OK);
12353b160b8bSBrian Somers }
12363b160b8bSBrian Somers
12373b160b8bSBrian Somers /* Outside World Access
12383b160b8bSBrian Somers
12393efa11bbSBrian Somers PacketAliasSaveFragment()
12403efa11bbSBrian Somers PacketAliasGetFragment()
12413efa11bbSBrian Somers PacketAliasFragmentIn()
12423b160b8bSBrian Somers PacketAliasIn()
12433b160b8bSBrian Somers PacketAliasOut()
1244642e43b3SArchie Cobbs PacketUnaliasOut()
12453b160b8bSBrian Somers
12463b160b8bSBrian Somers (prototypes in alias.h)
12473b160b8bSBrian Somers */
12483b160b8bSBrian Somers
12493b160b8bSBrian Somers int
LibAliasSaveFragment(struct libalias * la,void * ptr)1250bc596e56SAlex Richardson LibAliasSaveFragment(struct libalias *la, void *ptr)
12513b160b8bSBrian Somers {
12523b160b8bSBrian Somers int iresult;
1253ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
12543b160b8bSBrian Somers struct ip *pip;
12553b160b8bSBrian Somers
1256ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
12573b160b8bSBrian Somers pip = (struct ip *)ptr;
1258ed01a582SDag-Erling Smørgrav lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
12593b160b8bSBrian Somers iresult = PKT_ALIAS_ERROR;
1260ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
1261ed01a582SDag-Erling Smørgrav SetFragmentPtr(lnk, ptr);
12623b160b8bSBrian Somers iresult = PKT_ALIAS_OK;
12633b160b8bSBrian Somers }
1264ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
12653b160b8bSBrian Somers return (iresult);
12663b160b8bSBrian Somers }
12673b160b8bSBrian Somers
1268bc596e56SAlex Richardson void *
LibAliasGetFragment(struct libalias * la,void * ptr)1269bc596e56SAlex Richardson LibAliasGetFragment(struct libalias *la, void *ptr)
12703b160b8bSBrian Somers {
1271ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
1272bc596e56SAlex Richardson void *fptr;
12733b160b8bSBrian Somers struct ip *pip;
12743b160b8bSBrian Somers
1275ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
12763b160b8bSBrian Somers pip = (struct ip *)ptr;
1277ed01a582SDag-Erling Smørgrav lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1278ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
1279ed01a582SDag-Erling Smørgrav GetFragmentPtr(lnk, &fptr);
1280ed01a582SDag-Erling Smørgrav SetFragmentPtr(lnk, NULL);
1281ed01a582SDag-Erling Smørgrav SetExpire(lnk, 0); /* Deletes link */
1282ccd57eeaSPaolo Pisati } else
1283ccd57eeaSPaolo Pisati fptr = NULL;
12843b160b8bSBrian Somers
1285ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
12863b160b8bSBrian Somers return (fptr);
12873b160b8bSBrian Somers }
12883b160b8bSBrian Somers
12893b160b8bSBrian Somers void
LibAliasFragmentIn(struct libalias * la,void * ptr,void * ptr_fragment)1290effc8e57SLutz Donnerhacke LibAliasFragmentIn(struct libalias *la,
1291effc8e57SLutz Donnerhacke void *ptr, /* Points to correctly de-aliased header fragment */
1292effc8e57SLutz Donnerhacke void *ptr_fragment /* fragment which must be de-aliased */
12933b160b8bSBrian Somers )
12943b160b8bSBrian Somers {
12953b160b8bSBrian Somers struct ip *pip;
12963b160b8bSBrian Somers struct ip *fpip;
12973b160b8bSBrian Somers
1298ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1299ed01a582SDag-Erling Smørgrav (void)la;
13003b160b8bSBrian Somers pip = (struct ip *)ptr;
13013b160b8bSBrian Somers fpip = (struct ip *)ptr_fragment;
13023b160b8bSBrian Somers
13033b160b8bSBrian Somers DifferentialChecksum(&fpip->ip_sum,
13042871c501SDag-Erling Smørgrav &pip->ip_dst, &fpip->ip_dst, 2);
13053b160b8bSBrian Somers fpip->ip_dst = pip->ip_dst;
1306ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
13073b160b8bSBrian Somers }
13083b160b8bSBrian Somers
1309ccd57eeaSPaolo Pisati /* Local prototypes */
1310ccd57eeaSPaolo Pisati static int
1311bc596e56SAlex Richardson LibAliasOutLocked(struct libalias *la, struct ip *pip,
1312ccd57eeaSPaolo Pisati int maxpacketsize, int create);
1313ccd57eeaSPaolo Pisati static int
1314bc596e56SAlex Richardson LibAliasInLocked(struct libalias *la, struct ip *pip,
1315ccd57eeaSPaolo Pisati int maxpacketsize);
13163b160b8bSBrian Somers
13173b160b8bSBrian Somers int
LibAliasIn(struct libalias * la,void * ptr,int maxpacketsize)1318bc596e56SAlex Richardson LibAliasIn(struct libalias *la, void *ptr, int maxpacketsize)
13193b160b8bSBrian Somers {
1320ccd57eeaSPaolo Pisati int res;
1321ccd57eeaSPaolo Pisati
1322ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1323bc596e56SAlex Richardson res = LibAliasInLocked(la, (struct ip *)ptr, maxpacketsize);
1324ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
1325ccd57eeaSPaolo Pisati return (res);
1326ccd57eeaSPaolo Pisati }
1327ccd57eeaSPaolo Pisati
1328ccd57eeaSPaolo Pisati static int
LibAliasInLocked(struct libalias * la,struct ip * pip,int maxpacketsize)1329bc596e56SAlex Richardson LibAliasInLocked(struct libalias *la, struct ip *pip, int maxpacketsize)
1330ccd57eeaSPaolo Pisati {
13313b160b8bSBrian Somers struct in_addr alias_addr;
13323b160b8bSBrian Somers int iresult;
13333b160b8bSBrian Somers
13345e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
13355e289f9eSPoul-Henning Kamp la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1336bc596e56SAlex Richardson iresult = LibAliasOutLocked(la, pip, maxpacketsize, 1);
13375e289f9eSPoul-Henning Kamp la->packetAliasMode |= PKT_ALIAS_REVERSE;
1338ccd57eeaSPaolo Pisati goto getout;
13390622eafcSBrian Somers }
13405e289f9eSPoul-Henning Kamp HouseKeeping(la);
13413b160b8bSBrian Somers alias_addr = pip->ip_dst;
13423b160b8bSBrian Somers
13438ddc51bcSEivind Eklund /* Defense against mangled packets */
13448ddc51bcSEivind Eklund if (ntohs(pip->ip_len) > maxpacketsize
1345ccd57eeaSPaolo Pisati || (pip->ip_hl << 2) > maxpacketsize) {
1346ccd57eeaSPaolo Pisati iresult = PKT_ALIAS_IGNORED;
1347ccd57eeaSPaolo Pisati goto getout;
1348ccd57eeaSPaolo Pisati }
13498ddc51bcSEivind Eklund
1350461e6f23SMaxim Sobolev if (FRAG_NO_HDR(pip)) {
1351461e6f23SMaxim Sobolev iresult = FragmentIn(la, pip->ip_src, pip, pip->ip_id,
1352461e6f23SMaxim Sobolev &pip->ip_sum);
1353461e6f23SMaxim Sobolev goto getout;
1354461e6f23SMaxim Sobolev }
1355461e6f23SMaxim Sobolev
13563b160b8bSBrian Somers iresult = PKT_ALIAS_IGNORED;
1357f0f93429SDag-Erling Smørgrav switch (pip->ip_p) {
13583b160b8bSBrian Somers case IPPROTO_ICMP:
13595e289f9eSPoul-Henning Kamp iresult = IcmpAliasIn(la, pip);
13603b160b8bSBrian Somers break;
13613b160b8bSBrian Somers case IPPROTO_UDP:
13625e289f9eSPoul-Henning Kamp iresult = UdpAliasIn(la, pip);
13633b160b8bSBrian Somers break;
13643b160b8bSBrian Somers case IPPROTO_TCP:
13655e289f9eSPoul-Henning Kamp iresult = TcpAliasIn(la, pip);
13663b160b8bSBrian Somers break;
136737ce2656SPaolo Pisati #ifdef _KERNEL
136837ce2656SPaolo Pisati case IPPROTO_SCTP:
136937ce2656SPaolo Pisati iresult = SctpAlias(la, pip, SN_TO_LOCAL);
137037ce2656SPaolo Pisati break;
137137ce2656SPaolo Pisati #endif
1372be4f3cd0SPaolo Pisati case IPPROTO_GRE: {
1373be4f3cd0SPaolo Pisati int error;
1374be4f3cd0SPaolo Pisati struct alias_data ad = {
1375be4f3cd0SPaolo Pisati .lnk = NULL,
1376be4f3cd0SPaolo Pisati .oaddr = NULL,
1377be4f3cd0SPaolo Pisati .aaddr = NULL,
1378be4f3cd0SPaolo Pisati .aport = NULL,
1379be4f3cd0SPaolo Pisati .sport = NULL,
1380be4f3cd0SPaolo Pisati .dport = NULL,
1381be4f3cd0SPaolo Pisati .maxpktsize = 0
1382be4f3cd0SPaolo Pisati };
1383be4f3cd0SPaolo Pisati
1384be4f3cd0SPaolo Pisati /* Walk out chain. */
1385be4f3cd0SPaolo Pisati error = find_handler(IN, IP, la, pip, &ad);
1386be4f3cd0SPaolo Pisati if (error == 0)
138703453c5eSRuslan Ermilov iresult = PKT_ALIAS_OK;
138803453c5eSRuslan Ermilov else
1389ab0fcfd0SPaolo Pisati iresult = ProtoAliasIn(la, pip->ip_src,
1390bc596e56SAlex Richardson pip, pip->ip_p, &pip->ip_sum);
139155a39fc5SRuslan Ermilov break;
1392effc8e57SLutz Donnerhacke }
139380607605SRuslan Ermilov default:
1394bc596e56SAlex Richardson iresult = ProtoAliasIn(la, pip->ip_src, pip,
1395ab0fcfd0SPaolo Pisati pip->ip_p, &pip->ip_sum);
13967d96f4efSBrian Somers break;
13973b160b8bSBrian Somers }
13983b160b8bSBrian Somers
1399461e6f23SMaxim Sobolev if (MF_ISSET(pip)) {
1400ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
14013b160b8bSBrian Somers
1402ed01a582SDag-Erling Smørgrav lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1403ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
14043b160b8bSBrian Somers iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1405ed01a582SDag-Erling Smørgrav SetFragmentAddr(lnk, pip->ip_dst);
1406f0f93429SDag-Erling Smørgrav } else {
14073b160b8bSBrian Somers iresult = PKT_ALIAS_ERROR;
14083b160b8bSBrian Somers }
14093b160b8bSBrian Somers }
14103b160b8bSBrian Somers
1411ccd57eeaSPaolo Pisati getout:
14123b160b8bSBrian Somers return (iresult);
14133b160b8bSBrian Somers }
14143b160b8bSBrian Somers
14153b160b8bSBrian Somers /* Unregistered address ranges */
14163b160b8bSBrian Somers
14173b160b8bSBrian Somers /* 10.0.0.0 -> 10.255.255.255 */
14183b160b8bSBrian Somers #define UNREG_ADDR_A_LOWER 0x0a000000
14193b160b8bSBrian Somers #define UNREG_ADDR_A_UPPER 0x0affffff
14203b160b8bSBrian Somers
14213b160b8bSBrian Somers /* 172.16.0.0 -> 172.31.255.255 */
14223b160b8bSBrian Somers #define UNREG_ADDR_B_LOWER 0xac100000
14233b160b8bSBrian Somers #define UNREG_ADDR_B_UPPER 0xac1fffff
14243b160b8bSBrian Somers
14253b160b8bSBrian Somers /* 192.168.0.0 -> 192.168.255.255 */
14263b160b8bSBrian Somers #define UNREG_ADDR_C_LOWER 0xc0a80000
14273b160b8bSBrian Somers #define UNREG_ADDR_C_UPPER 0xc0a8ffff
14283b160b8bSBrian Somers
142975b89337SAlexander V. Chernikov /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */
143075b89337SAlexander V. Chernikov #define UNREG_ADDR_CGN_LOWER 0x64400000
143175b89337SAlexander V. Chernikov #define UNREG_ADDR_CGN_UPPER 0x647fffff
143275b89337SAlexander V. Chernikov
14333b160b8bSBrian Somers int
LibAliasOut(struct libalias * la,void * ptr,int maxpacketsize)1434bc596e56SAlex Richardson LibAliasOut(struct libalias *la, void *ptr, int maxpacketsize)
14353b160b8bSBrian Somers {
1436ccd57eeaSPaolo Pisati int res;
1437ccd57eeaSPaolo Pisati
1438ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1439bc596e56SAlex Richardson res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, 1);
1440ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
1441ccd57eeaSPaolo Pisati return (res);
1442e6bbb691SPoul-Henning Kamp }
1443e6bbb691SPoul-Henning Kamp
1444e6bbb691SPoul-Henning Kamp int
LibAliasOutTry(struct libalias * la,void * ptr,int maxpacketsize,int create)1445bc596e56SAlex Richardson LibAliasOutTry(struct libalias *la, void *ptr, int maxpacketsize, int create)
1446ccd57eeaSPaolo Pisati {
1447ccd57eeaSPaolo Pisati int res;
1448ccd57eeaSPaolo Pisati
1449ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1450bc596e56SAlex Richardson res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, create);
1451ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
1452ccd57eeaSPaolo Pisati return (res);
1453ccd57eeaSPaolo Pisati }
1454ccd57eeaSPaolo Pisati
1455ccd57eeaSPaolo Pisati static int
LibAliasOutLocked(struct libalias * la,struct ip * pip,int maxpacketsize,int create)1456effc8e57SLutz Donnerhacke LibAliasOutLocked(struct libalias *la,
1457effc8e57SLutz Donnerhacke struct ip *pip, /* valid IP packet */
1458effc8e57SLutz Donnerhacke int maxpacketsize, /* How much the packet data may grow (FTP and IRC inline changes) */
1459e6bbb691SPoul-Henning Kamp int create /* Create new entries ? */
1460e6bbb691SPoul-Henning Kamp )
1461e6bbb691SPoul-Henning Kamp {
14623b160b8bSBrian Somers int iresult;
14633b160b8bSBrian Somers struct in_addr addr_save;
14643b160b8bSBrian Somers
14655e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
14665e289f9eSPoul-Henning Kamp la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1467bc596e56SAlex Richardson iresult = LibAliasInLocked(la, pip, maxpacketsize);
14685e289f9eSPoul-Henning Kamp la->packetAliasMode |= PKT_ALIAS_REVERSE;
1469ccd57eeaSPaolo Pisati goto getout;
14700622eafcSBrian Somers }
14715e289f9eSPoul-Henning Kamp HouseKeeping(la);
14723b160b8bSBrian Somers
14738ddc51bcSEivind Eklund /* Defense against mangled packets */
14748ddc51bcSEivind Eklund if (ntohs(pip->ip_len) > maxpacketsize
1475ccd57eeaSPaolo Pisati || (pip->ip_hl << 2) > maxpacketsize) {
1476ccd57eeaSPaolo Pisati iresult = PKT_ALIAS_IGNORED;
1477ccd57eeaSPaolo Pisati goto getout;
1478ccd57eeaSPaolo Pisati }
14798ddc51bcSEivind Eklund
14805e289f9eSPoul-Henning Kamp addr_save = GetDefaultAliasAddress(la);
148175b89337SAlexander V. Chernikov if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY ||
148275b89337SAlexander V. Chernikov la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) {
1483483d2f22SRuslan Ermilov u_long addr;
14843b160b8bSBrian Somers int iclass;
14853b160b8bSBrian Somers
14863b160b8bSBrian Somers iclass = 0;
14873b160b8bSBrian Somers addr = ntohl(pip->ip_src.s_addr);
14883b160b8bSBrian Somers if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
14893b160b8bSBrian Somers iclass = 3;
14903b160b8bSBrian Somers else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
14913b160b8bSBrian Somers iclass = 2;
14923b160b8bSBrian Somers else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
14933b160b8bSBrian Somers iclass = 1;
149475b89337SAlexander V. Chernikov else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER &&
149575b89337SAlexander V. Chernikov la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN)
149675b89337SAlexander V. Chernikov iclass = 4;
14973b160b8bSBrian Somers
1498f0f93429SDag-Erling Smørgrav if (iclass == 0) {
14995e289f9eSPoul-Henning Kamp SetDefaultAliasAddress(la, pip->ip_src);
15003b160b8bSBrian Somers }
1501f0f93429SDag-Erling Smørgrav } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
15025e289f9eSPoul-Henning Kamp SetDefaultAliasAddress(la, pip->ip_src);
1503ada24e69SRuslan Ermilov }
1504461e6f23SMaxim Sobolev
1505461e6f23SMaxim Sobolev if (FRAG_NO_HDR(pip)) {
1506461e6f23SMaxim Sobolev iresult = FragmentOut(la, pip, &pip->ip_sum);
1507461e6f23SMaxim Sobolev goto getout_restore;
1508461e6f23SMaxim Sobolev }
1509461e6f23SMaxim Sobolev
15103b160b8bSBrian Somers iresult = PKT_ALIAS_IGNORED;
1511f0f93429SDag-Erling Smørgrav switch (pip->ip_p) {
15123b160b8bSBrian Somers case IPPROTO_ICMP:
1513e6bbb691SPoul-Henning Kamp iresult = IcmpAliasOut(la, pip, create);
15143b160b8bSBrian Somers break;
15153b160b8bSBrian Somers case IPPROTO_UDP:
1516ea29dd92SAlexander Motin iresult = UdpAliasOut(la, pip, maxpacketsize, create);
15173b160b8bSBrian Somers break;
15183b160b8bSBrian Somers case IPPROTO_TCP:
1519e6bbb691SPoul-Henning Kamp iresult = TcpAliasOut(la, pip, maxpacketsize, create);
15203b160b8bSBrian Somers break;
152137ce2656SPaolo Pisati #ifdef _KERNEL
152237ce2656SPaolo Pisati case IPPROTO_SCTP:
152337ce2656SPaolo Pisati iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
152437ce2656SPaolo Pisati break;
152537ce2656SPaolo Pisati #endif
1526be4f3cd0SPaolo Pisati case IPPROTO_GRE: {
1527be4f3cd0SPaolo Pisati int error;
1528be4f3cd0SPaolo Pisati struct alias_data ad = {
1529be4f3cd0SPaolo Pisati .lnk = NULL,
1530be4f3cd0SPaolo Pisati .oaddr = NULL,
1531be4f3cd0SPaolo Pisati .aaddr = NULL,
1532be4f3cd0SPaolo Pisati .aport = NULL,
1533be4f3cd0SPaolo Pisati .sport = NULL,
1534be4f3cd0SPaolo Pisati .dport = NULL,
1535be4f3cd0SPaolo Pisati .maxpktsize = 0
1536be4f3cd0SPaolo Pisati };
1537be4f3cd0SPaolo Pisati /* Walk out chain. */
1538be4f3cd0SPaolo Pisati error = find_handler(OUT, IP, la, pip, &ad);
1539be4f3cd0SPaolo Pisati if (error == 0)
154003453c5eSRuslan Ermilov iresult = PKT_ALIAS_OK;
154103453c5eSRuslan Ermilov else
1542bc596e56SAlex Richardson iresult = ProtoAliasOut(la, pip,
1543ab0fcfd0SPaolo Pisati pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
154403453c5eSRuslan Ermilov break;
1545effc8e57SLutz Donnerhacke }
154680607605SRuslan Ermilov default:
1547bc596e56SAlex Richardson iresult = ProtoAliasOut(la, pip,
1548ab0fcfd0SPaolo Pisati pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
15497d96f4efSBrian Somers break;
15503b160b8bSBrian Somers }
15513b160b8bSBrian Somers
1552461e6f23SMaxim Sobolev getout_restore:
15535e289f9eSPoul-Henning Kamp SetDefaultAliasAddress(la, addr_save);
1554ccd57eeaSPaolo Pisati getout:
15553b160b8bSBrian Somers return (iresult);
15563b160b8bSBrian Somers }
1557642e43b3SArchie Cobbs
1558642e43b3SArchie Cobbs int
LibAliasUnaliasOut(struct libalias * la,void * ptr,int maxpacketsize)1559effc8e57SLutz Donnerhacke LibAliasUnaliasOut(struct libalias *la,
1560effc8e57SLutz Donnerhacke void *ptr, /* valid IP packet */
1561642e43b3SArchie Cobbs int maxpacketsize /* for error checking */
1562642e43b3SArchie Cobbs )
1563642e43b3SArchie Cobbs {
1564642e43b3SArchie Cobbs struct ip *pip;
1565642e43b3SArchie Cobbs struct icmp *ic;
1566642e43b3SArchie Cobbs struct udphdr *ud;
1567642e43b3SArchie Cobbs struct tcphdr *tc;
1568ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
1569642e43b3SArchie Cobbs int iresult = PKT_ALIAS_IGNORED;
1570642e43b3SArchie Cobbs
1571ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1572642e43b3SArchie Cobbs pip = (struct ip *)ptr;
1573642e43b3SArchie Cobbs
1574642e43b3SArchie Cobbs /* Defense against mangled packets */
1575642e43b3SArchie Cobbs if (ntohs(pip->ip_len) > maxpacketsize
1576642e43b3SArchie Cobbs || (pip->ip_hl << 2) > maxpacketsize)
1577ccd57eeaSPaolo Pisati goto getout;
1578642e43b3SArchie Cobbs
15799fa0fd26SDag-Erling Smørgrav ud = (struct udphdr *)ip_next(pip);
15809fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
15819fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
1582642e43b3SArchie Cobbs
1583642e43b3SArchie Cobbs /* Find a link */
1584642e43b3SArchie Cobbs if (pip->ip_p == IPPROTO_UDP)
1585ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1586642e43b3SArchie Cobbs ud->uh_dport, ud->uh_sport,
1587642cd09fSRuslan Ermilov IPPROTO_UDP, 0);
1588642e43b3SArchie Cobbs else if (pip->ip_p == IPPROTO_TCP)
1589ed01a582SDag-Erling Smørgrav lnk = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1590642e43b3SArchie Cobbs tc->th_dport, tc->th_sport,
1591642cd09fSRuslan Ermilov IPPROTO_TCP, 0);
1592642e43b3SArchie Cobbs else if (pip->ip_p == IPPROTO_ICMP)
1593ed01a582SDag-Erling Smørgrav lnk = FindIcmpIn(la, pip->ip_dst, pip->ip_src, ic->icmp_id, 0);
1594642e43b3SArchie Cobbs else
1595ed01a582SDag-Erling Smørgrav lnk = NULL;
1596642e43b3SArchie Cobbs
1597642e43b3SArchie Cobbs /* Change it from an aliased packet to an unaliased packet */
1598ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
1599f0f93429SDag-Erling Smørgrav if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1600642e43b3SArchie Cobbs int accumulate;
1601642e43b3SArchie Cobbs struct in_addr original_address;
1602642e43b3SArchie Cobbs u_short original_port;
1603642e43b3SArchie Cobbs
1604ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
1605ed01a582SDag-Erling Smørgrav original_port = GetOriginalPort(lnk);
1606642e43b3SArchie Cobbs
1607642e43b3SArchie Cobbs /* Adjust TCP/UDP checksum */
16082871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_src);
16092871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
1610642e43b3SArchie Cobbs
1611642e43b3SArchie Cobbs if (pip->ip_p == IPPROTO_UDP) {
1612642e43b3SArchie Cobbs accumulate += ud->uh_sport;
1613642e43b3SArchie Cobbs accumulate -= original_port;
161471593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1615642e43b3SArchie Cobbs } else {
1616642e43b3SArchie Cobbs accumulate += tc->th_sport;
1617642e43b3SArchie Cobbs accumulate -= original_port;
161871593f95SBrian Somers ADJUST_CHECKSUM(accumulate, tc->th_sum);
1619642e43b3SArchie Cobbs }
1620642e43b3SArchie Cobbs
1621642e43b3SArchie Cobbs /* Adjust IP checksum */
1622642e43b3SArchie Cobbs DifferentialChecksum(&pip->ip_sum,
16232871c501SDag-Erling Smørgrav &original_address, &pip->ip_src, 2);
1624642e43b3SArchie Cobbs
1625642e43b3SArchie Cobbs /* Un-alias source address and port number */
1626642e43b3SArchie Cobbs pip->ip_src = original_address;
1627642e43b3SArchie Cobbs if (pip->ip_p == IPPROTO_UDP)
1628642e43b3SArchie Cobbs ud->uh_sport = original_port;
1629642e43b3SArchie Cobbs else
1630642e43b3SArchie Cobbs tc->th_sport = original_port;
1631642e43b3SArchie Cobbs
1632642e43b3SArchie Cobbs iresult = PKT_ALIAS_OK;
1633642e43b3SArchie Cobbs } else if (pip->ip_p == IPPROTO_ICMP) {
1634642e43b3SArchie Cobbs int accumulate;
1635642e43b3SArchie Cobbs struct in_addr original_address;
1636642e43b3SArchie Cobbs u_short original_id;
1637642e43b3SArchie Cobbs
1638ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
1639ed01a582SDag-Erling Smørgrav original_id = GetOriginalPort(lnk);
1640642e43b3SArchie Cobbs
1641642e43b3SArchie Cobbs /* Adjust ICMP checksum */
16422871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_src);
16432871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
1644642e43b3SArchie Cobbs accumulate += ic->icmp_id;
1645642e43b3SArchie Cobbs accumulate -= original_id;
164671593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1647642e43b3SArchie Cobbs
1648642e43b3SArchie Cobbs /* Adjust IP checksum */
1649642e43b3SArchie Cobbs DifferentialChecksum(&pip->ip_sum,
16502871c501SDag-Erling Smørgrav &original_address, &pip->ip_src, 2);
1651642e43b3SArchie Cobbs
1652642e43b3SArchie Cobbs /* Un-alias source address and port number */
1653642e43b3SArchie Cobbs pip->ip_src = original_address;
1654642e43b3SArchie Cobbs ic->icmp_id = original_id;
1655642e43b3SArchie Cobbs
1656642e43b3SArchie Cobbs iresult = PKT_ALIAS_OK;
1657642e43b3SArchie Cobbs }
1658642e43b3SArchie Cobbs }
1659ccd57eeaSPaolo Pisati getout:
1660ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
1661642e43b3SArchie Cobbs return (iresult);
1662642e43b3SArchie Cobbs }
1663be4f3cd0SPaolo Pisati
1664be4f3cd0SPaolo Pisati #ifndef _KERNEL
1665be4f3cd0SPaolo Pisati
1666be4f3cd0SPaolo Pisati int
LibAliasRefreshModules(void)1667be4f3cd0SPaolo Pisati LibAliasRefreshModules(void)
1668be4f3cd0SPaolo Pisati {
1669be4f3cd0SPaolo Pisati char buf[256], conf[] = "/etc/libalias.conf";
1670be4f3cd0SPaolo Pisati FILE *fd;
16715910c1c1SPaolo Pisati int i, len;
1672be4f3cd0SPaolo Pisati
1673be4f3cd0SPaolo Pisati fd = fopen(conf, "r");
1674be4f3cd0SPaolo Pisati if (fd == NULL)
1675be4f3cd0SPaolo Pisati err(1, "fopen(%s)", conf);
1676be4f3cd0SPaolo Pisati
1677be4f3cd0SPaolo Pisati LibAliasUnLoadAllModule();
1678be4f3cd0SPaolo Pisati
1679be4f3cd0SPaolo Pisati for (;;) {
1680be4f3cd0SPaolo Pisati fgets(buf, 256, fd);
168103bc210eSDmitry Morozovsky if (feof(fd))
1682be4f3cd0SPaolo Pisati break;
1683be4f3cd0SPaolo Pisati len = strlen(buf);
1684be4f3cd0SPaolo Pisati if (len > 1) {
16855910c1c1SPaolo Pisati for (i = 0; i < len; i++)
16865910c1c1SPaolo Pisati if (!isspace(buf[i]))
16875910c1c1SPaolo Pisati break;
16885910c1c1SPaolo Pisati if (buf[i] == '#')
16895910c1c1SPaolo Pisati continue;
1690be4f3cd0SPaolo Pisati buf[len - 1] = '\0';
1691be4f3cd0SPaolo Pisati LibAliasLoadModule(buf);
1692be4f3cd0SPaolo Pisati }
1693be4f3cd0SPaolo Pisati }
1694621882f0SChristian Brueffer fclose(fd);
1695be4f3cd0SPaolo Pisati return (0);
1696be4f3cd0SPaolo Pisati }
1697be4f3cd0SPaolo Pisati
1698be4f3cd0SPaolo Pisati int
LibAliasLoadModule(char * path)1699be4f3cd0SPaolo Pisati LibAliasLoadModule(char *path)
1700be4f3cd0SPaolo Pisati {
1701be4f3cd0SPaolo Pisati struct dll *t;
1702be4f3cd0SPaolo Pisati void *handle;
1703be4f3cd0SPaolo Pisati struct proto_handler *m;
1704be4f3cd0SPaolo Pisati const char *error;
1705be4f3cd0SPaolo Pisati moduledata_t *p;
1706be4f3cd0SPaolo Pisati
1707be4f3cd0SPaolo Pisati handle = dlopen (path, RTLD_LAZY);
1708be4f3cd0SPaolo Pisati if (!handle) {
17095910c1c1SPaolo Pisati fprintf(stderr, "%s\n", dlerror());
1710be4f3cd0SPaolo Pisati return (EINVAL);
1711be4f3cd0SPaolo Pisati }
1712be4f3cd0SPaolo Pisati
1713be4f3cd0SPaolo Pisati p = dlsym(handle, "alias_mod");
1714be4f3cd0SPaolo Pisati if ((error = dlerror()) != NULL) {
17155910c1c1SPaolo Pisati fprintf(stderr, "%s\n", dlerror());
1716be4f3cd0SPaolo Pisati return (EINVAL);
1717be4f3cd0SPaolo Pisati }
1718be4f3cd0SPaolo Pisati
1719be4f3cd0SPaolo Pisati t = malloc(sizeof(struct dll));
1720be4f3cd0SPaolo Pisati if (t == NULL)
1721be4f3cd0SPaolo Pisati return (ENOMEM);
1722be4f3cd0SPaolo Pisati strncpy(t->name, p->name, DLL_LEN);
1723be4f3cd0SPaolo Pisati t->handle = handle;
1724be4f3cd0SPaolo Pisati if (attach_dll(t) == EEXIST) {
1725be4f3cd0SPaolo Pisati free(t);
17265910c1c1SPaolo Pisati fprintf(stderr, "dll conflict\n");
1727be4f3cd0SPaolo Pisati return (EEXIST);
1728be4f3cd0SPaolo Pisati }
1729be4f3cd0SPaolo Pisati
1730be4f3cd0SPaolo Pisati m = dlsym(t->handle, "handlers");
1731be4f3cd0SPaolo Pisati if ((error = dlerror()) != NULL) {
17325910c1c1SPaolo Pisati fprintf(stderr, "%s\n", error);
1733be4f3cd0SPaolo Pisati return (EINVAL);
1734be4f3cd0SPaolo Pisati }
1735be4f3cd0SPaolo Pisati
1736be4f3cd0SPaolo Pisati LibAliasAttachHandlers(m);
1737be4f3cd0SPaolo Pisati return (0);
1738be4f3cd0SPaolo Pisati }
1739be4f3cd0SPaolo Pisati
1740be4f3cd0SPaolo Pisati int
LibAliasUnLoadAllModule(void)1741be4f3cd0SPaolo Pisati LibAliasUnLoadAllModule(void)
1742be4f3cd0SPaolo Pisati {
1743be4f3cd0SPaolo Pisati struct dll *t;
1744be4f3cd0SPaolo Pisati struct proto_handler *p;
1745be4f3cd0SPaolo Pisati
1746be4f3cd0SPaolo Pisati /* Unload all modules then reload everything. */
1747be4f3cd0SPaolo Pisati while ((p = first_handler()) != NULL) {
1748ec5df3a7SGleb Smirnoff LibAliasDetachHandlers(p);
1749be4f3cd0SPaolo Pisati }
1750be4f3cd0SPaolo Pisati while ((t = walk_dll_chain()) != NULL) {
1751be4f3cd0SPaolo Pisati dlclose(t->handle);
1752be4f3cd0SPaolo Pisati free(t);
1753be4f3cd0SPaolo Pisati }
1754be4f3cd0SPaolo Pisati return (1);
1755be4f3cd0SPaolo Pisati }
1756be4f3cd0SPaolo Pisati
1757be4f3cd0SPaolo Pisati #endif
1758e876228eSPaolo Pisati
1759e876228eSPaolo Pisati #ifdef _KERNEL
1760e876228eSPaolo Pisati /*
1761ccd57eeaSPaolo Pisati * m_megapullup() - this function is a big hack.
1762ccd57eeaSPaolo Pisati * Thankfully, it's only used in ng_nat and ipfw+nat.
1763e876228eSPaolo Pisati *
1764efc66711SAlexander Motin * It allocates an mbuf with cluster and copies the specified part of the chain
1765efc66711SAlexander Motin * into cluster, so that it is all contiguous and can be accessed via a plain
1766efc66711SAlexander Motin * (char *) pointer. This is required, because libalias doesn't know how to
1767efc66711SAlexander Motin * handle mbuf chains.
1768e876228eSPaolo Pisati *
1769efc66711SAlexander Motin * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1770efc66711SAlexander Motin * the input packet, on failure NULL. The input packet is always consumed.
1771e876228eSPaolo Pisati */
1772e876228eSPaolo Pisati struct mbuf *
m_megapullup(struct mbuf * m,int len)1773eb548a1aSAndrey V. Elsukov m_megapullup(struct mbuf *m, int len)
1774eb548a1aSAndrey V. Elsukov {
1775e876228eSPaolo Pisati struct mbuf *mcl;
1776e876228eSPaolo Pisati
1777efc66711SAlexander Motin if (len > m->m_pkthdr.len)
1778e876228eSPaolo Pisati goto bad;
1779e876228eSPaolo Pisati
17807525c481SGleb Smirnoff if (m->m_next == NULL && M_WRITABLE(m))
1781efc66711SAlexander Motin return (m);
1782efc66711SAlexander Motin
1783eb548a1aSAndrey V. Elsukov if (len <= MJUMPAGESIZE)
17847525c481SGleb Smirnoff mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
1785eb548a1aSAndrey V. Elsukov else if (len <= MJUM9BYTES)
1786eb548a1aSAndrey V. Elsukov mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1787eb548a1aSAndrey V. Elsukov else if (len <= MJUM16BYTES)
1788eb548a1aSAndrey V. Elsukov mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
1789eb548a1aSAndrey V. Elsukov else
1790eb548a1aSAndrey V. Elsukov goto bad;
1791efc66711SAlexander Motin if (mcl == NULL)
1792e876228eSPaolo Pisati goto bad;
17937525c481SGleb Smirnoff m_align(mcl, len);
1794e876228eSPaolo Pisati m_move_pkthdr(mcl, m);
1795efc66711SAlexander Motin m_copydata(m, 0, len, mtod(mcl, caddr_t));
1796efc66711SAlexander Motin mcl->m_len = mcl->m_pkthdr.len = len;
1797e876228eSPaolo Pisati m_freem(m);
1798e876228eSPaolo Pisati
1799e876228eSPaolo Pisati return (mcl);
1800e876228eSPaolo Pisati bad:
1801e876228eSPaolo Pisati m_freem(m);
1802e876228eSPaolo Pisati return (NULL);
1803e876228eSPaolo Pisati }
1804e876228eSPaolo Pisati #endif
1805