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 */
1860fc7bdc9SRichard Scheffenegger static void TcpMonitorIn(uint16_t, struct alias_link *);
1873b160b8bSBrian Somers
1880fc7bdc9SRichard Scheffenegger static void TcpMonitorOut(uint16_t, struct alias_link *);
1893b160b8bSBrian Somers
1903b160b8bSBrian Somers static void
TcpMonitorIn(uint16_t th_flags,struct alias_link * lnk)1910fc7bdc9SRichard 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)2080fc7bdc9SRichard 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;
293*fb2ea26fSMark Johnston int ret;
2943b160b8bSBrian Somers
2952e6b0786SLutz Donnerhacke LIBALIAS_LOCK_ASSERT(la);
2969fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
2973b160b8bSBrian Somers
2983b160b8bSBrian Somers /* Get source address from ICMP data field and restore original data */
299*fb2ea26fSMark Johnston ret = FindIcmpIn(la, pip->ip_src, pip->ip_dst, ic->icmp_id, 1, &lnk);
300*fb2ea26fSMark Johnston if (ret == PKT_ALIAS_OK) {
3013b160b8bSBrian Somers u_short original_id;
3023b160b8bSBrian Somers int accumulate;
3033b160b8bSBrian Somers
304ed01a582SDag-Erling Smørgrav original_id = GetOriginalPort(lnk);
3053b160b8bSBrian Somers
3063b160b8bSBrian Somers /* Adjust ICMP checksum */
3073b160b8bSBrian Somers accumulate = ic->icmp_id;
3083b160b8bSBrian Somers accumulate -= original_id;
30971593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
3103b160b8bSBrian Somers
3113b160b8bSBrian Somers /* Put original sequence number back in */
3123b160b8bSBrian Somers ic->icmp_id = original_id;
3133b160b8bSBrian Somers
3143b160b8bSBrian Somers /* Put original address back into IP header */
3153b160b8bSBrian Somers {
3163b160b8bSBrian Somers struct in_addr original_address;
3173b160b8bSBrian Somers
318ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
3193b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
3202871c501SDag-Erling Smørgrav &original_address, &pip->ip_dst, 2);
3213b160b8bSBrian Somers pip->ip_dst = original_address;
3223b160b8bSBrian Somers }
3233b160b8bSBrian Somers }
324*fb2ea26fSMark Johnston return (ret);
3253b160b8bSBrian Somers }
3263b160b8bSBrian Somers
3273b160b8bSBrian Somers /*
3283b160b8bSBrian Somers Alias incoming ICMP error messages containing
3293b160b8bSBrian Somers IP header and first 64 bits of datagram.
3303b160b8bSBrian Somers */
331effc8e57SLutz Donnerhacke static int
IcmpAliasIn2(struct libalias * la,struct ip * pip)332effc8e57SLutz Donnerhacke IcmpAliasIn2(struct libalias *la, struct ip *pip)
333effc8e57SLutz Donnerhacke {
3343b160b8bSBrian Somers struct ip *ip;
3353b160b8bSBrian Somers struct icmp *ic, *ic2;
3363b160b8bSBrian Somers struct udphdr *ud;
3373b160b8bSBrian Somers struct tcphdr *tc;
338ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
339*fb2ea26fSMark Johnston int ret;
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
349*fb2ea26fSMark Johnston if (ip->ip_p == IPPROTO_UDP) {
350*fb2ea26fSMark Johnston ret = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
3513b160b8bSBrian Somers ud->uh_dport, ud->uh_sport,
352*fb2ea26fSMark Johnston IPPROTO_UDP, 0, &lnk);
353*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
354*fb2ea26fSMark Johnston return (ret);
355*fb2ea26fSMark Johnston } else if (ip->ip_p == IPPROTO_TCP) {
356*fb2ea26fSMark Johnston ret = FindUdpTcpIn(la, ip->ip_dst, ip->ip_src,
3573b160b8bSBrian Somers tc->th_dport, tc->th_sport,
358*fb2ea26fSMark Johnston IPPROTO_TCP, 0, &lnk);
359*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
360*fb2ea26fSMark Johnston return (ret);
361*fb2ea26fSMark Johnston } else if (ip->ip_p == IPPROTO_ICMP) {
362*fb2ea26fSMark Johnston if (ic2->icmp_type == ICMP_ECHO ||
363*fb2ea26fSMark Johnston ic2->icmp_type == ICMP_TSTAMP) {
364*fb2ea26fSMark Johnston ret = FindIcmpIn(la, ip->ip_dst, ip->ip_src,
365*fb2ea26fSMark Johnston ic2->icmp_id, 0, &lnk);
366*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
367*fb2ea26fSMark Johnston return (ret);
368*fb2ea26fSMark Johnston } else
369ed01a582SDag-Erling Smørgrav lnk = NULL;
370dfcb634bSBrian Somers } else
371ed01a582SDag-Erling Smørgrav lnk = NULL;
3723b160b8bSBrian Somers
373ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
374f0f93429SDag-Erling Smørgrav if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
37561a875d7SRuslan Ermilov int accumulate, accumulate2;
3763b160b8bSBrian Somers struct in_addr original_address;
3773b160b8bSBrian Somers u_short original_port;
3783b160b8bSBrian Somers
379ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
380ed01a582SDag-Erling Smørgrav original_port = GetOriginalPort(lnk);
3813b160b8bSBrian Somers
3823b160b8bSBrian Somers /* Adjust ICMP checksum */
3832871c501SDag-Erling Smørgrav accumulate = twowords(&ip->ip_src);
3842871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
3853b160b8bSBrian Somers accumulate += ud->uh_sport;
3863b160b8bSBrian Somers accumulate -= original_port;
38761a875d7SRuslan Ermilov accumulate2 = accumulate;
38861a875d7SRuslan Ermilov accumulate2 += ip->ip_sum;
38961a875d7SRuslan Ermilov ADJUST_CHECKSUM(accumulate, ip->ip_sum);
39061a875d7SRuslan Ermilov accumulate2 -= ip->ip_sum;
39161a875d7SRuslan Ermilov ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
3923b160b8bSBrian Somers
3933b160b8bSBrian Somers /* Un-alias address in IP header */
3943b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
3952871c501SDag-Erling Smørgrav &original_address, &pip->ip_dst, 2);
3963b160b8bSBrian Somers pip->ip_dst = original_address;
3973b160b8bSBrian Somers
398effc8e57SLutz Donnerhacke /* Un-alias address and port number of
399effc8e57SLutz Donnerhacke * original IP packet fragment contained
400effc8e57SLutz Donnerhacke * in ICMP data section */
4013b160b8bSBrian Somers ip->ip_src = original_address;
4023b160b8bSBrian Somers ud->uh_sport = original_port;
403f0f93429SDag-Erling Smørgrav } else if (ip->ip_p == IPPROTO_ICMP) {
40461a875d7SRuslan Ermilov int accumulate, accumulate2;
4053b160b8bSBrian Somers struct in_addr original_address;
4063b160b8bSBrian Somers u_short original_id;
4073b160b8bSBrian Somers
408ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
409ed01a582SDag-Erling Smørgrav original_id = GetOriginalPort(lnk);
4103b160b8bSBrian Somers
4113b160b8bSBrian Somers /* Adjust ICMP checksum */
4122871c501SDag-Erling Smørgrav accumulate = twowords(&ip->ip_src);
4132871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
4143b160b8bSBrian Somers accumulate += ic2->icmp_id;
4153b160b8bSBrian Somers accumulate -= original_id;
41661a875d7SRuslan Ermilov accumulate2 = accumulate;
41761a875d7SRuslan Ermilov accumulate2 += ip->ip_sum;
41861a875d7SRuslan Ermilov ADJUST_CHECKSUM(accumulate, ip->ip_sum);
41961a875d7SRuslan Ermilov accumulate2 -= ip->ip_sum;
42061a875d7SRuslan Ermilov ADJUST_CHECKSUM(accumulate2, ic->icmp_cksum);
4213b160b8bSBrian Somers
4223b160b8bSBrian Somers /* Un-alias address in IP header */
4233b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
4242871c501SDag-Erling Smørgrav &original_address, &pip->ip_dst, 2);
4253b160b8bSBrian Somers pip->ip_dst = original_address;
4263b160b8bSBrian Somers
427effc8e57SLutz Donnerhacke /* Un-alias address of original IP packet and
428effc8e57SLutz Donnerhacke * sequence number of embedded ICMP datagram */
4293b160b8bSBrian Somers ip->ip_src = original_address;
4303b160b8bSBrian Somers ic2->icmp_id = original_id;
4313b160b8bSBrian Somers }
4323b160b8bSBrian Somers return (PKT_ALIAS_OK);
4333b160b8bSBrian Somers }
4343b160b8bSBrian Somers return (PKT_ALIAS_IGNORED);
4353b160b8bSBrian Somers }
4363b160b8bSBrian Somers
4373b160b8bSBrian Somers static int
IcmpAliasIn(struct libalias * la,struct ip * pip)4385e289f9eSPoul-Henning Kamp IcmpAliasIn(struct libalias *la, struct ip *pip)
4393b160b8bSBrian Somers {
4403b160b8bSBrian Somers struct icmp *ic;
441be597269SAlex Richardson int iresult;
442be597269SAlex Richardson size_t dlen;
4433b160b8bSBrian Somers
444ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
4456461c83eSEd Maste
4466461c83eSEd Maste dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
4476461c83eSEd Maste if (dlen < ICMP_MINLEN)
4486461c83eSEd Maste return (PKT_ALIAS_IGNORED);
4496461c83eSEd Maste
4507d96f4efSBrian Somers /* Return if proxy-only mode is enabled */
4515e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
452ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
4537d96f4efSBrian Somers
4549fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
4553b160b8bSBrian Somers
4563b160b8bSBrian Somers iresult = PKT_ALIAS_IGNORED;
457f0f93429SDag-Erling Smørgrav switch (ic->icmp_type) {
4583b160b8bSBrian Somers case ICMP_ECHOREPLY:
4593b160b8bSBrian Somers case ICMP_TSTAMPREPLY:
460f0f93429SDag-Erling Smørgrav if (ic->icmp_code == 0) {
4615e289f9eSPoul-Henning Kamp iresult = IcmpAliasIn1(la, pip);
4623b160b8bSBrian Somers }
4633b160b8bSBrian Somers break;
4643b160b8bSBrian Somers case ICMP_UNREACH:
4653b160b8bSBrian Somers case ICMP_SOURCEQUENCH:
4663b160b8bSBrian Somers case ICMP_TIMXCEED:
4673b160b8bSBrian Somers case ICMP_PARAMPROB:
4686461c83eSEd Maste if (dlen < ICMP_ADVLENMIN ||
469be597269SAlex Richardson dlen < (size_t)ICMP_ADVLEN(ic))
4706461c83eSEd Maste return (PKT_ALIAS_IGNORED);
4715e289f9eSPoul-Henning Kamp iresult = IcmpAliasIn2(la, pip);
4723b160b8bSBrian Somers break;
4733b160b8bSBrian Somers case ICMP_ECHO:
4743b160b8bSBrian Somers case ICMP_TSTAMP:
4755e289f9eSPoul-Henning Kamp iresult = IcmpAliasIn1(la, pip);
4763b160b8bSBrian Somers break;
4773b160b8bSBrian Somers }
4783b160b8bSBrian Somers return (iresult);
4793b160b8bSBrian Somers }
4803b160b8bSBrian Somers
4813b160b8bSBrian Somers /*
482305d1069SRuslan Ermilov Alias outgoing echo and timestamp requests.
483305d1069SRuslan Ermilov De-alias outgoing echo and timestamp replies.
4843b160b8bSBrian Somers */
485effc8e57SLutz Donnerhacke static int
IcmpAliasOut1(struct libalias * la,struct ip * pip,int create)486effc8e57SLutz Donnerhacke IcmpAliasOut1(struct libalias *la, struct ip *pip, int create)
487effc8e57SLutz Donnerhacke {
488ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
4893b160b8bSBrian Somers struct icmp *ic;
490*fb2ea26fSMark Johnston int ret;
4913b160b8bSBrian Somers
492ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
4939fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
4943b160b8bSBrian Somers
4953b160b8bSBrian Somers /* Save overwritten data for when echo packet returns */
496*fb2ea26fSMark Johnston ret = FindIcmpOut(la, pip->ip_src, pip->ip_dst, ic->icmp_id, create,
497*fb2ea26fSMark Johnston &lnk);
498*fb2ea26fSMark Johnston if (ret == PKT_ALIAS_OK) {
4993b160b8bSBrian Somers u_short alias_id;
5003b160b8bSBrian Somers int accumulate;
5013b160b8bSBrian Somers
502ed01a582SDag-Erling Smørgrav alias_id = GetAliasPort(lnk);
5033b160b8bSBrian Somers
5043b160b8bSBrian Somers /* Since data field is being modified, adjust ICMP checksum */
5053b160b8bSBrian Somers accumulate = ic->icmp_id;
5063b160b8bSBrian Somers accumulate -= alias_id;
50771593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
5083b160b8bSBrian Somers
5093b160b8bSBrian Somers /* Alias sequence number */
5103b160b8bSBrian Somers ic->icmp_id = alias_id;
5113b160b8bSBrian Somers
5123b160b8bSBrian Somers /* Change source address */
5133b160b8bSBrian Somers {
5143b160b8bSBrian Somers struct in_addr alias_address;
5153b160b8bSBrian Somers
516ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
5173b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
5182871c501SDag-Erling Smørgrav &alias_address, &pip->ip_src, 2);
5193b160b8bSBrian Somers pip->ip_src = alias_address;
5203b160b8bSBrian Somers }
5213b160b8bSBrian Somers }
522*fb2ea26fSMark Johnston return (ret);
5233b160b8bSBrian Somers }
5243b160b8bSBrian Somers
5253b160b8bSBrian Somers /*
5263b160b8bSBrian Somers Alias outgoing ICMP error messages containing
5273b160b8bSBrian Somers IP header and first 64 bits of datagram.
5283b160b8bSBrian Somers */
529effc8e57SLutz Donnerhacke static int
IcmpAliasOut2(struct libalias * la,struct ip * pip)530effc8e57SLutz Donnerhacke IcmpAliasOut2(struct libalias *la, struct ip *pip)
531effc8e57SLutz Donnerhacke {
5323b160b8bSBrian Somers struct ip *ip;
533680c8244SRuslan Ermilov struct icmp *ic, *ic2;
534680c8244SRuslan Ermilov struct udphdr *ud;
535680c8244SRuslan Ermilov struct tcphdr *tc;
536ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
537*fb2ea26fSMark Johnston int ret;
5383b160b8bSBrian Somers
539ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
5409fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
541305d1069SRuslan Ermilov ip = &ic->icmp_ip;
5423b160b8bSBrian Somers
5439fa0fd26SDag-Erling Smørgrav ud = (struct udphdr *)ip_next(ip);
5449fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(ip);
5459fa0fd26SDag-Erling Smørgrav ic2 = (struct icmp *)ip_next(ip);
5463b160b8bSBrian Somers
547*fb2ea26fSMark Johnston if (ip->ip_p == IPPROTO_UDP) {
548*fb2ea26fSMark Johnston ret = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
549680c8244SRuslan Ermilov ud->uh_dport, ud->uh_sport,
550*fb2ea26fSMark Johnston IPPROTO_UDP, 0, &lnk);
551*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
552*fb2ea26fSMark Johnston return (ret);
553*fb2ea26fSMark Johnston } else if (ip->ip_p == IPPROTO_TCP) {
554*fb2ea26fSMark Johnston ret = FindUdpTcpOut(la, ip->ip_dst, ip->ip_src,
555680c8244SRuslan Ermilov tc->th_dport, tc->th_sport,
556*fb2ea26fSMark Johnston IPPROTO_TCP, 0, &lnk);
557*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
558*fb2ea26fSMark Johnston return (ret);
559*fb2ea26fSMark Johnston } else if (ip->ip_p == IPPROTO_ICMP) {
560*fb2ea26fSMark Johnston if (ic2->icmp_type == ICMP_ECHO ||
561*fb2ea26fSMark Johnston ic2->icmp_type == ICMP_TSTAMP) {
562*fb2ea26fSMark Johnston ret = FindIcmpOut(la, ip->ip_dst, ip->ip_src,
563*fb2ea26fSMark Johnston ic2->icmp_id, 0, &lnk);
564*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
565*fb2ea26fSMark Johnston return (ret);
566*fb2ea26fSMark Johnston } else
567ed01a582SDag-Erling Smørgrav lnk = NULL;
568680c8244SRuslan Ermilov } else
569ed01a582SDag-Erling Smørgrav lnk = NULL;
5703b160b8bSBrian Somers
571ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
572f0f93429SDag-Erling Smørgrav if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
573680c8244SRuslan Ermilov int accumulate;
574680c8244SRuslan Ermilov struct in_addr alias_address;
575680c8244SRuslan Ermilov u_short alias_port;
576680c8244SRuslan Ermilov
577ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
578ed01a582SDag-Erling Smørgrav alias_port = GetAliasPort(lnk);
579680c8244SRuslan Ermilov
580680c8244SRuslan Ermilov /* Adjust ICMP checksum */
5812871c501SDag-Erling Smørgrav accumulate = twowords(&ip->ip_dst);
5822871c501SDag-Erling Smørgrav accumulate -= twowords(&alias_address);
583680c8244SRuslan Ermilov accumulate += ud->uh_dport;
584680c8244SRuslan Ermilov accumulate -= alias_port;
58571593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
586680c8244SRuslan Ermilov
587816fa7feSRuslan Ermilov /*
588816fa7feSRuslan Ermilov * Alias address in IP header if it comes from the host
589816fa7feSRuslan Ermilov * the original TCP/UDP packet was destined for.
590816fa7feSRuslan Ermilov */
591816fa7feSRuslan Ermilov if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
5923b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
5932871c501SDag-Erling Smørgrav &alias_address, &pip->ip_src, 2);
594680c8244SRuslan Ermilov pip->ip_src = alias_address;
595816fa7feSRuslan Ermilov }
596680c8244SRuslan Ermilov /* Alias address and port number of original IP packet
597effc8e57SLutz Donnerhacke * fragment contained in ICMP data section */
598680c8244SRuslan Ermilov ip->ip_dst = alias_address;
599680c8244SRuslan Ermilov ud->uh_dport = alias_port;
600f0f93429SDag-Erling Smørgrav } else if (ip->ip_p == IPPROTO_ICMP) {
601680c8244SRuslan Ermilov int accumulate;
602680c8244SRuslan Ermilov struct in_addr alias_address;
603680c8244SRuslan Ermilov u_short alias_id;
604680c8244SRuslan Ermilov
605ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
606ed01a582SDag-Erling Smørgrav alias_id = GetAliasPort(lnk);
607680c8244SRuslan Ermilov
608680c8244SRuslan Ermilov /* Adjust ICMP checksum */
6092871c501SDag-Erling Smørgrav accumulate = twowords(&ip->ip_dst);
6102871c501SDag-Erling Smørgrav accumulate -= twowords(&alias_address);
611680c8244SRuslan Ermilov accumulate += ic2->icmp_id;
612680c8244SRuslan Ermilov accumulate -= alias_id;
61371593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
614680c8244SRuslan Ermilov
615816fa7feSRuslan Ermilov /*
616816fa7feSRuslan Ermilov * Alias address in IP header if it comes from the host
617816fa7feSRuslan Ermilov * the original ICMP message was destined for.
618816fa7feSRuslan Ermilov */
619816fa7feSRuslan Ermilov if (pip->ip_src.s_addr == ip->ip_dst.s_addr) {
620680c8244SRuslan Ermilov DifferentialChecksum(&pip->ip_sum,
6212871c501SDag-Erling Smørgrav &alias_address, &pip->ip_src, 2);
622680c8244SRuslan Ermilov pip->ip_src = alias_address;
623816fa7feSRuslan Ermilov }
624effc8e57SLutz Donnerhacke /* Alias address of original IP packet and
625effc8e57SLutz Donnerhacke * sequence number of embedded ICMP datagram */
626680c8244SRuslan Ermilov ip->ip_dst = alias_address;
627680c8244SRuslan Ermilov ic2->icmp_id = alias_id;
628680c8244SRuslan Ermilov }
629680c8244SRuslan Ermilov return (PKT_ALIAS_OK);
630680c8244SRuslan Ermilov }
631680c8244SRuslan Ermilov return (PKT_ALIAS_IGNORED);
6323b160b8bSBrian Somers }
6333b160b8bSBrian Somers
6343b160b8bSBrian Somers static int
IcmpAliasOut(struct libalias * la,struct ip * pip,int create)635e6bbb691SPoul-Henning Kamp IcmpAliasOut(struct libalias *la, struct ip *pip, int create)
6363b160b8bSBrian Somers {
6373b160b8bSBrian Somers int iresult;
6383b160b8bSBrian Somers struct icmp *ic;
6393b160b8bSBrian Somers
640ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
641ed01a582SDag-Erling Smørgrav (void)create;
642ed01a582SDag-Erling Smørgrav
6437d96f4efSBrian Somers /* Return if proxy-only mode is enabled */
6445e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
645ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
6467d96f4efSBrian Somers
6479fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
6483b160b8bSBrian Somers
6493b160b8bSBrian Somers iresult = PKT_ALIAS_IGNORED;
650f0f93429SDag-Erling Smørgrav switch (ic->icmp_type) {
6513b160b8bSBrian Somers case ICMP_ECHO:
6523b160b8bSBrian Somers case ICMP_TSTAMP:
653f0f93429SDag-Erling Smørgrav if (ic->icmp_code == 0) {
654e7581f0fSPoul-Henning Kamp iresult = IcmpAliasOut1(la, pip, create);
6553b160b8bSBrian Somers }
6563b160b8bSBrian Somers break;
6573b160b8bSBrian Somers case ICMP_UNREACH:
6583b160b8bSBrian Somers case ICMP_SOURCEQUENCH:
6593b160b8bSBrian Somers case ICMP_TIMXCEED:
6603b160b8bSBrian Somers case ICMP_PARAMPROB:
6615e289f9eSPoul-Henning Kamp iresult = IcmpAliasOut2(la, pip);
6623b160b8bSBrian Somers break;
6633b160b8bSBrian Somers case ICMP_ECHOREPLY:
6643b160b8bSBrian Somers case ICMP_TSTAMPREPLY:
665e7581f0fSPoul-Henning Kamp iresult = IcmpAliasOut1(la, pip, create);
6663b160b8bSBrian Somers }
6673b160b8bSBrian Somers return (iresult);
6683b160b8bSBrian Somers }
6693b160b8bSBrian Somers
6707d96f4efSBrian Somers /*
67180607605SRuslan Ermilov Handle incoming IP packets. The
6727d96f4efSBrian Somers only thing which is done in this case is to alias
6737d96f4efSBrian Somers the dest IP address of the packet to our inside
6747d96f4efSBrian Somers machine.
6757d96f4efSBrian Somers */
676effc8e57SLutz Donnerhacke static int
ProtoAliasIn(struct libalias * la,struct in_addr ip_src,struct ip * pip,u_char ip_p,u_short * ip_sum)677effc8e57SLutz Donnerhacke ProtoAliasIn(struct libalias *la, struct in_addr ip_src,
678effc8e57SLutz Donnerhacke struct ip *pip, u_char ip_p, u_short *ip_sum)
679effc8e57SLutz Donnerhacke {
680ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
681*fb2ea26fSMark Johnston int ret;
6827d96f4efSBrian Somers
683ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
684483d2f22SRuslan Ermilov /* Return if proxy-only mode is enabled */
6855e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
686ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
687483d2f22SRuslan Ermilov
688*fb2ea26fSMark Johnston ret = FindProtoIn(la, ip_src, pip->ip_dst, ip_p, &lnk);
689*fb2ea26fSMark Johnston if (ret == PKT_ALIAS_OK) {
690483d2f22SRuslan Ermilov struct in_addr original_address;
6917d96f4efSBrian Somers
692ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
693483d2f22SRuslan Ermilov
694483d2f22SRuslan Ermilov /* Restore original IP address */
695ab0fcfd0SPaolo Pisati DifferentialChecksum(ip_sum,
696bc596e56SAlex Richardson &original_address, &pip->ip_dst, 2);
697bc596e56SAlex Richardson pip->ip_dst = original_address;
698483d2f22SRuslan Ermilov }
699*fb2ea26fSMark Johnston return (ret);
7007d96f4efSBrian Somers }
7017d96f4efSBrian Somers
7027d96f4efSBrian Somers /*
70380607605SRuslan Ermilov Handle outgoing IP packets. The
7047d96f4efSBrian Somers only thing which is done in this case is to alias
7057d96f4efSBrian Somers the source IP address of the packet.
7067d96f4efSBrian Somers */
707effc8e57SLutz 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)708effc8e57SLutz Donnerhacke ProtoAliasOut(struct libalias *la, struct ip *pip,
709effc8e57SLutz Donnerhacke struct in_addr ip_dst, u_char ip_p, u_short *ip_sum, int create)
710effc8e57SLutz Donnerhacke {
711ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
712*fb2ea26fSMark Johnston int ret;
713ed01a582SDag-Erling Smørgrav
714ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
7157d96f4efSBrian Somers
716483d2f22SRuslan Ermilov /* Return if proxy-only mode is enabled */
7175e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
718ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
719483d2f22SRuslan Ermilov
7201a356b8bSEugene Grosbein if (!create)
7211a356b8bSEugene Grosbein return (PKT_ALIAS_IGNORED);
7221a356b8bSEugene Grosbein
723*fb2ea26fSMark Johnston ret = FindProtoOut(la, pip->ip_src, ip_dst, ip_p, &lnk);
724*fb2ea26fSMark Johnston if (ret == PKT_ALIAS_OK) {
725483d2f22SRuslan Ermilov struct in_addr alias_address;
7267d96f4efSBrian Somers
727ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
728483d2f22SRuslan Ermilov
729483d2f22SRuslan Ermilov /* Change source address */
730ab0fcfd0SPaolo Pisati DifferentialChecksum(ip_sum,
731bc596e56SAlex Richardson &alias_address, &pip->ip_src, 2);
732bc596e56SAlex Richardson pip->ip_src = alias_address;
733483d2f22SRuslan Ermilov }
734*fb2ea26fSMark Johnston return (ret);
7357d96f4efSBrian Somers }
7367d96f4efSBrian Somers
737461e6f23SMaxim Sobolev #define MF_ISSET(_pip) (ntohs((_pip)->ip_off) & IP_MF)
738461e6f23SMaxim Sobolev #define FRAG_NO_HDR(_pip) (ntohs((_pip)->ip_off) & IP_OFFMASK)
739461e6f23SMaxim Sobolev
740461e6f23SMaxim Sobolev static struct udphdr *
ValidateUdpLength(struct ip * pip)741461e6f23SMaxim Sobolev ValidateUdpLength(struct ip *pip)
742461e6f23SMaxim Sobolev {
743461e6f23SMaxim Sobolev struct udphdr *ud;
744461e6f23SMaxim Sobolev size_t dlen;
745461e6f23SMaxim Sobolev
746461e6f23SMaxim Sobolev #ifdef _KERNEL
747461e6f23SMaxim Sobolev KASSERT(!FRAG_NO_HDR(pip), ("header-less fragment isn't expected here"));
748461e6f23SMaxim Sobolev #endif
749461e6f23SMaxim Sobolev dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
750461e6f23SMaxim Sobolev if (dlen < sizeof(struct udphdr))
751461e6f23SMaxim Sobolev return (NULL);
752461e6f23SMaxim Sobolev ud = (struct udphdr *)ip_next(pip);
753461e6f23SMaxim Sobolev if (!MF_ISSET(pip) && dlen < ntohs(ud->uh_ulen))
754461e6f23SMaxim Sobolev return (NULL);
755461e6f23SMaxim Sobolev return (ud);
756461e6f23SMaxim Sobolev }
757461e6f23SMaxim Sobolev
75855a39fc5SRuslan Ermilov static int
UdpAliasIn(struct libalias * la,struct ip * pip)7595e289f9eSPoul-Henning Kamp UdpAliasIn(struct libalias *la, struct ip *pip)
7603b160b8bSBrian Somers {
7613b160b8bSBrian Somers struct udphdr *ud;
762ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
763*fb2ea26fSMark Johnston int ret;
7643b160b8bSBrian Somers
765ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
7667d96f4efSBrian Somers
767461e6f23SMaxim Sobolev ud = ValidateUdpLength(pip);
768461e6f23SMaxim Sobolev if (ud == NULL)
7696461c83eSEd Maste return (PKT_ALIAS_IGNORED);
7703b160b8bSBrian Somers
771*fb2ea26fSMark Johnston ret = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
7723b160b8bSBrian Somers ud->uh_sport, ud->uh_dport,
773*fb2ea26fSMark Johnston IPPROTO_UDP, !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY), &lnk);
774*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
775*fb2ea26fSMark Johnston return (ret);
776*fb2ea26fSMark Johnston {
7773b160b8bSBrian Somers struct in_addr alias_address;
7783b160b8bSBrian Somers struct in_addr original_address;
779ea29dd92SAlexander Motin struct in_addr proxy_address;
7803b160b8bSBrian Somers u_short alias_port;
781ea29dd92SAlexander Motin u_short proxy_port;
7823b160b8bSBrian Somers int accumulate;
783ea80b0acSPaolo Pisati int error;
784be4f3cd0SPaolo Pisati struct alias_data ad = {
785be4f3cd0SPaolo Pisati .lnk = lnk,
786be4f3cd0SPaolo Pisati .oaddr = &original_address,
787be4f3cd0SPaolo Pisati .aaddr = &alias_address,
788be4f3cd0SPaolo Pisati .aport = &alias_port,
789be4f3cd0SPaolo Pisati .sport = &ud->uh_sport,
790be4f3cd0SPaolo Pisati .dport = &ud->uh_dport,
791be4f3cd0SPaolo Pisati .maxpktsize = 0
792be4f3cd0SPaolo Pisati };
7933b160b8bSBrian Somers
794ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
795ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
796ea29dd92SAlexander Motin proxy_address = GetProxyAddress(lnk);
7973b160b8bSBrian Somers alias_port = ud->uh_dport;
798ed01a582SDag-Erling Smørgrav ud->uh_dport = GetOriginalPort(lnk);
799ea29dd92SAlexander Motin proxy_port = GetProxyPort(lnk);
8003b160b8bSBrian Somers
801be4f3cd0SPaolo Pisati /* Walk out chain. */
802be4f3cd0SPaolo Pisati error = find_handler(IN, UDP, la, pip, &ad);
80350d25ddaSPaolo Pisati /* If we cannot figure out the packet, ignore it. */
80450d25ddaSPaolo Pisati if (error < 0)
80550d25ddaSPaolo Pisati return (PKT_ALIAS_IGNORED);
8060579bd71SBrian Somers
807effc8e57SLutz Donnerhacke /* If UDP checksum is not zero, then adjust since
808effc8e57SLutz Donnerhacke * destination port is being unaliased and
809effc8e57SLutz Donnerhacke * destination address is being altered. */
810f0f93429SDag-Erling Smørgrav if (ud->uh_sum != 0) {
8113b160b8bSBrian Somers accumulate = alias_port;
8123b160b8bSBrian Somers accumulate -= ud->uh_dport;
8132871c501SDag-Erling Smørgrav accumulate += twowords(&alias_address);
8142871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
815ea29dd92SAlexander Motin
816effc8e57SLutz Donnerhacke /* If this is a proxy packet, modify checksum
817effc8e57SLutz Donnerhacke * because of source change.*/
818ea29dd92SAlexander Motin if (proxy_port != 0) {
819ea29dd92SAlexander Motin accumulate += ud->uh_sport;
820ea29dd92SAlexander Motin accumulate -= proxy_port;
821ea29dd92SAlexander Motin }
822ea29dd92SAlexander Motin
823ea29dd92SAlexander Motin if (proxy_address.s_addr != 0) {
824ea29dd92SAlexander Motin accumulate += twowords(&pip->ip_src);
825ea29dd92SAlexander Motin accumulate -= twowords(&proxy_address);
826ea29dd92SAlexander Motin }
827ea29dd92SAlexander Motin
82871593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ud->uh_sum);
8293b160b8bSBrian Somers }
830effc8e57SLutz Donnerhacke
831ea29dd92SAlexander Motin /* XXX: Could the two if's below be concatenated to one ? */
832ea29dd92SAlexander Motin /* Restore source port and/or address in case of proxying*/
833ea29dd92SAlexander Motin if (proxy_port != 0)
834ea29dd92SAlexander Motin ud->uh_sport = proxy_port;
835ea29dd92SAlexander Motin
836ea29dd92SAlexander Motin if (proxy_address.s_addr != 0) {
837ea29dd92SAlexander Motin DifferentialChecksum(&pip->ip_sum,
838ea29dd92SAlexander Motin &proxy_address, &pip->ip_src, 2);
839ea29dd92SAlexander Motin pip->ip_src = proxy_address;
840ea29dd92SAlexander Motin }
841ea29dd92SAlexander Motin
8423b160b8bSBrian Somers /* Restore original IP address */
8433b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
8442871c501SDag-Erling Smørgrav &original_address, &pip->ip_dst, 2);
8453b160b8bSBrian Somers pip->ip_dst = original_address;
846374fad8bSMatthew Dillon
8473b160b8bSBrian Somers return (PKT_ALIAS_OK);
8483b160b8bSBrian Somers }
8493b160b8bSBrian Somers }
8503b160b8bSBrian Somers
8513b160b8bSBrian Somers static int
UdpAliasOut(struct libalias * la,struct ip * pip,int maxpacketsize,int create)852ea29dd92SAlexander Motin UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
8533b160b8bSBrian Somers {
8543b160b8bSBrian Somers struct udphdr *ud;
855ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
856ea29dd92SAlexander Motin struct in_addr dest_address;
857ea29dd92SAlexander Motin struct in_addr proxy_server_address;
858ea29dd92SAlexander Motin u_short dest_port;
859ea29dd92SAlexander Motin u_short proxy_server_port;
860*fb2ea26fSMark Johnston int proxy_type, ret;
8613b160b8bSBrian Somers
862ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
863ea29dd92SAlexander Motin
864461e6f23SMaxim Sobolev ud = ValidateUdpLength(pip);
865461e6f23SMaxim Sobolev if (ud == NULL)
866461e6f23SMaxim Sobolev return (PKT_ALIAS_IGNORED);
867461e6f23SMaxim Sobolev
868ea29dd92SAlexander Motin /* Return if proxy-only mode is enabled and not proxyrule found.*/
869effc8e57SLutz Donnerhacke proxy_type = ProxyCheck(la, &proxy_server_address, &proxy_server_port,
870effc8e57SLutz Donnerhacke pip->ip_src, pip->ip_dst, ud->uh_dport, pip->ip_p);
871ea29dd92SAlexander Motin if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
872ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
8737d96f4efSBrian Somers
874ea29dd92SAlexander Motin /* If this is a transparent proxy, save original destination,
875ea29dd92SAlexander Motin * then alter the destination and adjust checksums */
876ea29dd92SAlexander Motin dest_port = ud->uh_dport;
877ea29dd92SAlexander Motin dest_address = pip->ip_dst;
8783b160b8bSBrian Somers
879ea29dd92SAlexander Motin if (proxy_type != 0) {
880ea29dd92SAlexander Motin int accumulate;
881ea29dd92SAlexander Motin
882ea29dd92SAlexander Motin accumulate = twowords(&pip->ip_dst);
883ea29dd92SAlexander Motin accumulate -= twowords(&proxy_server_address);
884ea29dd92SAlexander Motin
885ea29dd92SAlexander Motin ADJUST_CHECKSUM(accumulate, pip->ip_sum);
886ea29dd92SAlexander Motin
887ea29dd92SAlexander Motin if (ud->uh_sum != 0) {
888ea29dd92SAlexander Motin accumulate = twowords(&pip->ip_dst);
889ea29dd92SAlexander Motin accumulate -= twowords(&proxy_server_address);
890ea29dd92SAlexander Motin accumulate += ud->uh_dport;
891ea29dd92SAlexander Motin accumulate -= proxy_server_port;
892ea29dd92SAlexander Motin ADJUST_CHECKSUM(accumulate, ud->uh_sum);
893ea29dd92SAlexander Motin }
894ea29dd92SAlexander Motin pip->ip_dst = proxy_server_address;
895ea29dd92SAlexander Motin ud->uh_dport = proxy_server_port;
896ea29dd92SAlexander Motin }
897*fb2ea26fSMark Johnston ret = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
8983b160b8bSBrian Somers ud->uh_sport, ud->uh_dport,
899*fb2ea26fSMark Johnston IPPROTO_UDP, create, &lnk);
900*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
901*fb2ea26fSMark Johnston return (ret);
902*fb2ea26fSMark Johnston {
9033b160b8bSBrian Somers u_short alias_port;
9043b160b8bSBrian Somers struct in_addr alias_address;
905be4f3cd0SPaolo Pisati struct alias_data ad = {
906be4f3cd0SPaolo Pisati .lnk = lnk,
907be4f3cd0SPaolo Pisati .oaddr = NULL,
908be4f3cd0SPaolo Pisati .aaddr = &alias_address,
909be4f3cd0SPaolo Pisati .aport = &alias_port,
910be4f3cd0SPaolo Pisati .sport = &ud->uh_sport,
911be4f3cd0SPaolo Pisati .dport = &ud->uh_dport,
912be4f3cd0SPaolo Pisati .maxpktsize = 0
913be4f3cd0SPaolo Pisati };
9143b160b8bSBrian Somers
915ea29dd92SAlexander Motin /* Save original destination address, if this is a proxy packet.
916ea29dd92SAlexander Motin * Also modify packet to include destination encoding. This may
917ea29dd92SAlexander Motin * change the size of IP header. */
918ea29dd92SAlexander Motin if (proxy_type != 0) {
919ea29dd92SAlexander Motin SetProxyPort(lnk, dest_port);
920ea29dd92SAlexander Motin SetProxyAddress(lnk, dest_address);
921ea29dd92SAlexander Motin ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
922ea29dd92SAlexander Motin ud = (struct udphdr *)ip_next(pip);
923ea29dd92SAlexander Motin }
924ea29dd92SAlexander Motin
925ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
926ed01a582SDag-Erling Smørgrav alias_port = GetAliasPort(lnk);
9273b160b8bSBrian Somers
928be4f3cd0SPaolo Pisati /* Walk out chain. */
9296454d0c8SJohn Baldwin find_handler(OUT, UDP, la, pip, &ad);
930fb9cd36dSAtsushi Murai
9313b160b8bSBrian Somers /* If UDP checksum is not zero, adjust since source port is */
9323b160b8bSBrian Somers /* being aliased and source address is being altered */
933f0f93429SDag-Erling Smørgrav if (ud->uh_sum != 0) {
9343b160b8bSBrian Somers int accumulate;
9353b160b8bSBrian Somers
9363b160b8bSBrian Somers accumulate = ud->uh_sport;
9373b160b8bSBrian Somers accumulate -= alias_port;
9382871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_src);
9392871c501SDag-Erling Smørgrav accumulate -= twowords(&alias_address);
94071593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ud->uh_sum);
9413b160b8bSBrian Somers }
942fb9cd36dSAtsushi Murai /* Put alias port in UDP header */
9433b160b8bSBrian Somers ud->uh_sport = alias_port;
9443b160b8bSBrian Somers
9453b160b8bSBrian Somers /* Change source address */
9463b160b8bSBrian Somers DifferentialChecksum(&pip->ip_sum,
9472871c501SDag-Erling Smørgrav &alias_address, &pip->ip_src, 2);
9483b160b8bSBrian Somers pip->ip_src = alias_address;
9493b160b8bSBrian Somers
9503b160b8bSBrian Somers return (PKT_ALIAS_OK);
9513b160b8bSBrian Somers }
9523b160b8bSBrian Somers }
9533b160b8bSBrian Somers
9543b160b8bSBrian Somers static int
TcpAliasIn(struct libalias * la,struct ip * pip)9555e289f9eSPoul-Henning Kamp TcpAliasIn(struct libalias *la, struct ip *pip)
9563b160b8bSBrian Somers {
9573b160b8bSBrian Somers struct tcphdr *tc;
958ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
959be597269SAlex Richardson size_t dlen;
960*fb2ea26fSMark Johnston int ret;
9613b160b8bSBrian Somers
962ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
9636461c83eSEd Maste
9646461c83eSEd Maste dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
9656461c83eSEd Maste if (dlen < sizeof(struct tcphdr))
9666461c83eSEd Maste return (PKT_ALIAS_IGNORED);
9679fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
9683b160b8bSBrian Somers
969*fb2ea26fSMark Johnston ret = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
9703b160b8bSBrian Somers tc->th_sport, tc->th_dport,
971642cd09fSRuslan Ermilov IPPROTO_TCP,
972*fb2ea26fSMark Johnston !(la->packetAliasMode & PKT_ALIAS_PROXY_ONLY),
973*fb2ea26fSMark Johnston &lnk);
974*fb2ea26fSMark Johnston if (ret == PKT_ALIAS_OK) {
9753b160b8bSBrian Somers struct in_addr alias_address;
9763b160b8bSBrian Somers struct in_addr original_address;
9777d96f4efSBrian Somers struct in_addr proxy_address;
9783b160b8bSBrian Somers u_short alias_port;
9797d96f4efSBrian Somers u_short proxy_port;
9806454d0c8SJohn Baldwin int accumulate;
9813b160b8bSBrian Somers
982be4f3cd0SPaolo Pisati /*
983be4f3cd0SPaolo Pisati * The init of MANY vars is a bit below, but aliashandlepptpin
984be4f3cd0SPaolo Pisati * seems to need the destination port that came within the
985be4f3cd0SPaolo Pisati * packet and not the original one looks below [*].
986be4f3cd0SPaolo Pisati */
987be4f3cd0SPaolo Pisati
988be4f3cd0SPaolo Pisati struct alias_data ad = {
989be4f3cd0SPaolo Pisati .lnk = lnk,
990be4f3cd0SPaolo Pisati .oaddr = NULL,
991be4f3cd0SPaolo Pisati .aaddr = NULL,
992be4f3cd0SPaolo Pisati .aport = NULL,
993be4f3cd0SPaolo Pisati .sport = &tc->th_sport,
994be4f3cd0SPaolo Pisati .dport = &tc->th_dport,
995be4f3cd0SPaolo Pisati .maxpktsize = 0
996be4f3cd0SPaolo Pisati };
997be4f3cd0SPaolo Pisati
998be4f3cd0SPaolo Pisati /* Walk out chain. */
9996454d0c8SJohn Baldwin find_handler(IN, TCP, la, pip, &ad);
100055a39fc5SRuslan Ermilov
1001ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
1002ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
1003ed01a582SDag-Erling Smørgrav proxy_address = GetProxyAddress(lnk);
10043b160b8bSBrian Somers alias_port = tc->th_dport;
1005ed01a582SDag-Erling Smørgrav tc->th_dport = GetOriginalPort(lnk);
1006ed01a582SDag-Erling Smørgrav proxy_port = GetProxyPort(lnk);
10073b160b8bSBrian Somers
1008be4f3cd0SPaolo Pisati /*
1009be4f3cd0SPaolo Pisati * Look above, if anyone is going to add find_handler AFTER
1010be4f3cd0SPaolo Pisati * this aliashandlepptpin/point, please redo alias_data too.
1011be4f3cd0SPaolo Pisati * Uncommenting the piece here below should be enough.
1012be4f3cd0SPaolo Pisati */
1013be4f3cd0SPaolo Pisati #if 0
1014be4f3cd0SPaolo Pisati struct alias_data ad = {
1015be4f3cd0SPaolo Pisati .lnk = lnk,
1016be4f3cd0SPaolo Pisati .oaddr = &original_address,
1017be4f3cd0SPaolo Pisati .aaddr = &alias_address,
1018be4f3cd0SPaolo Pisati .aport = &alias_port,
1019be4f3cd0SPaolo Pisati .sport = &ud->uh_sport,
1020be4f3cd0SPaolo Pisati .dport = &ud->uh_dport,
1021be4f3cd0SPaolo Pisati .maxpktsize = 0
1022be4f3cd0SPaolo Pisati };
1023be4f3cd0SPaolo Pisati
1024be4f3cd0SPaolo Pisati /* Walk out chain. */
1025be4f3cd0SPaolo Pisati error = find_handler(la, pip, &ad);
1026be4f3cd0SPaolo Pisati if (error == EHDNOF)
1027be4f3cd0SPaolo Pisati printf("Protocol handler not found\n");
1028be4f3cd0SPaolo Pisati #endif
1029be4f3cd0SPaolo Pisati
1030effc8e57SLutz Donnerhacke /* Adjust TCP checksum since destination port is being
1031effc8e57SLutz Donnerhacke * unaliased and destination port is being altered. */
10323b160b8bSBrian Somers accumulate = alias_port;
10333b160b8bSBrian Somers accumulate -= tc->th_dport;
10342871c501SDag-Erling Smørgrav accumulate += twowords(&alias_address);
10352871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
10363b160b8bSBrian Somers
1037effc8e57SLutz Donnerhacke /* If this is a proxy, then modify the TCP source port
1038effc8e57SLutz Donnerhacke * and checksum accumulation */
1039f0f93429SDag-Erling Smørgrav if (proxy_port != 0) {
10407d96f4efSBrian Somers accumulate += tc->th_sport;
10417d96f4efSBrian Somers tc->th_sport = proxy_port;
10427d96f4efSBrian Somers accumulate -= tc->th_sport;
10432871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_src);
10442871c501SDag-Erling Smørgrav accumulate -= twowords(&proxy_address);
10457d96f4efSBrian Somers }
1046483d2f22SRuslan Ermilov /* See if ACK number needs to be modified */
1047ed01a582SDag-Erling Smørgrav if (GetAckModified(lnk) == 1) {
10483b160b8bSBrian Somers int delta;
10493b160b8bSBrian Somers
10504741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
10514741f3a1SPaolo Pisati delta = GetDeltaAckIn(tc->th_ack, lnk);
1052f0f93429SDag-Erling Smørgrav if (delta != 0) {
10532871c501SDag-Erling Smørgrav accumulate += twowords(&tc->th_ack);
10543b160b8bSBrian Somers tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
10552871c501SDag-Erling Smørgrav accumulate -= twowords(&tc->th_ack);
10563b160b8bSBrian Somers }
10573b160b8bSBrian Somers }
10583b160b8bSBrian Somers ADJUST_CHECKSUM(accumulate, tc->th_sum);
10593b160b8bSBrian Somers
10603b160b8bSBrian Somers /* Restore original IP address */
10612871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_dst);
1062ab39bc9aSDaniel Eischen pip->ip_dst = original_address;
10632871c501SDag-Erling Smørgrav accumulate -= twowords(&pip->ip_dst);
10647d96f4efSBrian Somers
1065effc8e57SLutz Donnerhacke /* If this is a transparent proxy packet,
1066effc8e57SLutz Donnerhacke * then modify the source address */
1067f0f93429SDag-Erling Smørgrav if (proxy_address.s_addr != 0) {
10682871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_src);
10697d96f4efSBrian Somers pip->ip_src = proxy_address;
10702871c501SDag-Erling Smørgrav accumulate -= twowords(&pip->ip_src);
10717d96f4efSBrian Somers }
10727d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum);
10733b160b8bSBrian Somers
10743b160b8bSBrian Somers /* Monitor TCP connection state */
10754741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
10760fc7bdc9SRichard Scheffenegger TcpMonitorIn(__tcp_get_flags(tc), lnk);
10773b160b8bSBrian Somers
10783b160b8bSBrian Somers return (PKT_ALIAS_OK);
10793b160b8bSBrian Somers }
1080*fb2ea26fSMark Johnston return (ret);
10813b160b8bSBrian Somers }
10823b160b8bSBrian Somers
10833b160b8bSBrian Somers static int
TcpAliasOut(struct libalias * la,struct ip * pip,int maxpacketsize,int create)1084e6bbb691SPoul-Henning Kamp TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
10853b160b8bSBrian Somers {
1086*fb2ea26fSMark Johnston int proxy_type, ret;
10877d96f4efSBrian Somers u_short dest_port;
10887d96f4efSBrian Somers u_short proxy_server_port;
1089be597269SAlex Richardson size_t dlen;
10907d96f4efSBrian Somers struct in_addr dest_address;
10917d96f4efSBrian Somers struct in_addr proxy_server_address;
10923b160b8bSBrian Somers struct tcphdr *tc;
1093ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
10943b160b8bSBrian Somers
1095ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
10966461c83eSEd Maste
10976461c83eSEd Maste dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
10986461c83eSEd Maste if (dlen < sizeof(struct tcphdr))
10996461c83eSEd Maste return (PKT_ALIAS_IGNORED);
11009fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
11013b160b8bSBrian Somers
1102dca9c930SPoul-Henning Kamp if (create)
11034741f3a1SPaolo Pisati proxy_type = ProxyCheck(la, &proxy_server_address,
11044741f3a1SPaolo Pisati &proxy_server_port, pip->ip_src, pip->ip_dst,
11054741f3a1SPaolo Pisati tc->th_dport, pip->ip_p);
1106dca9c930SPoul-Henning Kamp else
1107dca9c930SPoul-Henning Kamp proxy_type = 0;
11087d96f4efSBrian Somers
11095e289f9eSPoul-Henning Kamp if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY))
1110ffcb611aSDag-Erling Smørgrav return (PKT_ALIAS_OK);
11117d96f4efSBrian Somers
11127d96f4efSBrian Somers /* If this is a transparent proxy, save original destination,
1113effc8e57SLutz Donnerhacke * then alter the destination and adjust checksums */
11147d96f4efSBrian Somers dest_port = tc->th_dport;
11157d96f4efSBrian Somers dest_address = pip->ip_dst;
1116f0f93429SDag-Erling Smørgrav if (proxy_type != 0) {
11177d96f4efSBrian Somers int accumulate;
11187d96f4efSBrian Somers
11197d96f4efSBrian Somers accumulate = tc->th_dport;
11207d96f4efSBrian Somers tc->th_dport = proxy_server_port;
11217d96f4efSBrian Somers accumulate -= tc->th_dport;
11222871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_dst);
11232871c501SDag-Erling Smørgrav accumulate -= twowords(&proxy_server_address);
11247d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, tc->th_sum);
11257d96f4efSBrian Somers
11262871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_dst);
11277d96f4efSBrian Somers pip->ip_dst = proxy_server_address;
11282871c501SDag-Erling Smørgrav accumulate -= twowords(&pip->ip_dst);
11297d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum);
11307d96f4efSBrian Somers }
1131*fb2ea26fSMark Johnston ret = FindUdpTcpOut(la, pip->ip_src, pip->ip_dst,
11323b160b8bSBrian Somers tc->th_sport, tc->th_dport,
1133*fb2ea26fSMark Johnston IPPROTO_TCP, create, &lnk);
1134*fb2ea26fSMark Johnston if (ret != PKT_ALIAS_OK)
1135*fb2ea26fSMark Johnston return (ret);
1136*fb2ea26fSMark Johnston {
11373b160b8bSBrian Somers u_short alias_port;
11387d96f4efSBrian Somers struct in_addr alias_address;
11393b160b8bSBrian Somers int accumulate;
1140be4f3cd0SPaolo Pisati struct alias_data ad = {
1141be4f3cd0SPaolo Pisati .lnk = lnk,
1142be4f3cd0SPaolo Pisati .oaddr = NULL,
1143be4f3cd0SPaolo Pisati .aaddr = &alias_address,
1144be4f3cd0SPaolo Pisati .aport = &alias_port,
1145be4f3cd0SPaolo Pisati .sport = &tc->th_sport,
1146be4f3cd0SPaolo Pisati .dport = &tc->th_dport,
1147be4f3cd0SPaolo Pisati .maxpktsize = maxpacketsize
1148be4f3cd0SPaolo Pisati };
11493b160b8bSBrian Somers
11507d96f4efSBrian Somers /* Save original destination address, if this is a proxy packet.
1151effc8e57SLutz Donnerhacke * Also modify packet to include destination
1152effc8e57SLutz Donnerhacke * encoding. This may change the size of IP header. */
1153f0f93429SDag-Erling Smørgrav if (proxy_type != 0) {
1154ed01a582SDag-Erling Smørgrav SetProxyPort(lnk, dest_port);
1155ed01a582SDag-Erling Smørgrav SetProxyAddress(lnk, dest_address);
1156ed01a582SDag-Erling Smørgrav ProxyModify(la, lnk, pip, maxpacketsize, proxy_type);
11579fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
11587d96f4efSBrian Somers }
11597d96f4efSBrian Somers /* Get alias address and port */
1160ed01a582SDag-Erling Smørgrav alias_port = GetAliasPort(lnk);
1161ed01a582SDag-Erling Smørgrav alias_address = GetAliasAddress(lnk);
11623b160b8bSBrian Somers
1163483d2f22SRuslan Ermilov /* Monitor TCP connection state */
11644741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
11650fc7bdc9SRichard Scheffenegger TcpMonitorOut(__tcp_get_flags(tc), lnk);
11663b160b8bSBrian Somers
1167be4f3cd0SPaolo Pisati /* Walk out chain. */
11686454d0c8SJohn Baldwin find_handler(OUT, TCP, la, pip, &ad);
11693b160b8bSBrian Somers
1170effc8e57SLutz Donnerhacke /* Adjust TCP checksum since source port is being aliased
1171effc8e57SLutz Donnerhacke * and source address is being altered */
11723b160b8bSBrian Somers accumulate = tc->th_sport;
11737d96f4efSBrian Somers tc->th_sport = alias_port;
11747d96f4efSBrian Somers accumulate -= tc->th_sport;
11752871c501SDag-Erling Smørgrav accumulate += twowords(&pip->ip_src);
11762871c501SDag-Erling Smørgrav accumulate -= twowords(&alias_address);
11773b160b8bSBrian Somers
11783b160b8bSBrian Somers /* Modify sequence number if necessary */
1179ed01a582SDag-Erling Smørgrav if (GetAckModified(lnk) == 1) {
11803b160b8bSBrian Somers int delta;
11813b160b8bSBrian Somers
11824741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
11834741f3a1SPaolo Pisati delta = GetDeltaSeqOut(tc->th_seq, lnk);
1184f0f93429SDag-Erling Smørgrav if (delta != 0) {
11852871c501SDag-Erling Smørgrav accumulate += twowords(&tc->th_seq);
11863b160b8bSBrian Somers tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
11872871c501SDag-Erling Smørgrav accumulate -= twowords(&tc->th_seq);
11883b160b8bSBrian Somers }
11893b160b8bSBrian Somers }
119071593f95SBrian Somers ADJUST_CHECKSUM(accumulate, tc->th_sum);
11913b160b8bSBrian Somers
11923b160b8bSBrian Somers /* Change source address */
11932871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_src);
11943b160b8bSBrian Somers pip->ip_src = alias_address;
11952871c501SDag-Erling Smørgrav accumulate -= twowords(&pip->ip_src);
119671593f95SBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum);
11973b160b8bSBrian Somers
11983b160b8bSBrian Somers return (PKT_ALIAS_OK);
11993b160b8bSBrian Somers }
12003b160b8bSBrian Somers }
12013b160b8bSBrian Somers
12023b160b8bSBrian Somers /* Fragment Handling
12033b160b8bSBrian Somers
12043b160b8bSBrian Somers FragmentIn()
12053b160b8bSBrian Somers FragmentOut()
12063b160b8bSBrian Somers
12073b160b8bSBrian Somers The packet aliasing module has a limited ability for handling IP
12083b160b8bSBrian Somers fragments. If the ICMP, TCP or UDP header is in the first fragment
1209483d2f22SRuslan Ermilov received, then the ID number of the IP packet is saved, and other
12103b160b8bSBrian Somers fragments are identified according to their ID number and IP address
12113b160b8bSBrian Somers they were sent from. Pointers to unresolved fragments can also be
12123b160b8bSBrian Somers saved and recalled when a header fragment is seen.
12133b160b8bSBrian Somers */
12143b160b8bSBrian Somers
12153b160b8bSBrian Somers /* Local prototypes */
1216ab0fcfd0SPaolo Pisati static int FragmentIn(struct libalias *la, struct in_addr ip_src,
1217bc596e56SAlex Richardson struct ip *pip, u_short ip_id, u_short *ip_sum);
1218bc596e56SAlex Richardson static int FragmentOut(struct libalias *, struct ip *pip,
1219ab0fcfd0SPaolo Pisati u_short *ip_sum);
12203b160b8bSBrian Somers
12213b160b8bSBrian Somers static int
FragmentIn(struct libalias * la,struct in_addr ip_src,struct ip * pip,u_short ip_id,u_short * ip_sum)1222bc596e56SAlex Richardson FragmentIn(struct libalias *la, struct in_addr ip_src, struct ip *pip,
1223aac54f0aSAlexander Motin u_short ip_id, u_short *ip_sum)
12243b160b8bSBrian Somers {
1225ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
12263b160b8bSBrian Somers
1227ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
1228bc596e56SAlex Richardson lnk = FindFragmentIn2(la, ip_src, pip->ip_dst, ip_id);
1229ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
12303b160b8bSBrian Somers struct in_addr original_address;
12313b160b8bSBrian Somers
1232ed01a582SDag-Erling Smørgrav GetFragmentAddr(lnk, &original_address);
1233ab0fcfd0SPaolo Pisati DifferentialChecksum(ip_sum,
1234bc596e56SAlex Richardson &original_address, &pip->ip_dst, 2);
1235bc596e56SAlex Richardson pip->ip_dst = original_address;
12363b160b8bSBrian Somers
12373b160b8bSBrian Somers return (PKT_ALIAS_OK);
12383b160b8bSBrian Somers }
12393b160b8bSBrian Somers return (PKT_ALIAS_UNRESOLVED_FRAGMENT);
12403b160b8bSBrian Somers }
12413b160b8bSBrian Somers
12423b160b8bSBrian Somers static int
FragmentOut(struct libalias * la,struct ip * pip,u_short * ip_sum)1243bc596e56SAlex Richardson FragmentOut(struct libalias *la, struct ip *pip, u_short *ip_sum)
12443b160b8bSBrian Somers {
12453b160b8bSBrian Somers struct in_addr alias_address;
12463b160b8bSBrian Somers
1247ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
1248bc596e56SAlex Richardson alias_address = FindAliasAddress(la, pip->ip_src);
1249ab0fcfd0SPaolo Pisati DifferentialChecksum(ip_sum,
1250bc596e56SAlex Richardson &alias_address, &pip->ip_src, 2);
1251bc596e56SAlex Richardson pip->ip_src = alias_address;
12523b160b8bSBrian Somers
12533b160b8bSBrian Somers return (PKT_ALIAS_OK);
12543b160b8bSBrian Somers }
12553b160b8bSBrian Somers
12563b160b8bSBrian Somers /* Outside World Access
12573b160b8bSBrian Somers
12583efa11bbSBrian Somers PacketAliasSaveFragment()
12593efa11bbSBrian Somers PacketAliasGetFragment()
12603efa11bbSBrian Somers PacketAliasFragmentIn()
12613b160b8bSBrian Somers PacketAliasIn()
12623b160b8bSBrian Somers PacketAliasOut()
1263642e43b3SArchie Cobbs PacketUnaliasOut()
12643b160b8bSBrian Somers
12653b160b8bSBrian Somers (prototypes in alias.h)
12663b160b8bSBrian Somers */
12673b160b8bSBrian Somers
12683b160b8bSBrian Somers int
LibAliasSaveFragment(struct libalias * la,void * ptr)1269bc596e56SAlex Richardson LibAliasSaveFragment(struct libalias *la, void *ptr)
12703b160b8bSBrian Somers {
12713b160b8bSBrian Somers int iresult;
1272ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
12733b160b8bSBrian Somers struct ip *pip;
12743b160b8bSBrian Somers
1275ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
12763b160b8bSBrian Somers pip = (struct ip *)ptr;
1277ed01a582SDag-Erling Smørgrav lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
12783b160b8bSBrian Somers iresult = PKT_ALIAS_ERROR;
1279ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
1280ed01a582SDag-Erling Smørgrav SetFragmentPtr(lnk, ptr);
12813b160b8bSBrian Somers iresult = PKT_ALIAS_OK;
12823b160b8bSBrian Somers }
1283ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
12843b160b8bSBrian Somers return (iresult);
12853b160b8bSBrian Somers }
12863b160b8bSBrian Somers
1287bc596e56SAlex Richardson void *
LibAliasGetFragment(struct libalias * la,void * ptr)1288bc596e56SAlex Richardson LibAliasGetFragment(struct libalias *la, void *ptr)
12893b160b8bSBrian Somers {
1290ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
1291bc596e56SAlex Richardson void *fptr;
12923b160b8bSBrian Somers struct ip *pip;
12933b160b8bSBrian Somers
1294ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
12953b160b8bSBrian Somers pip = (struct ip *)ptr;
1296ed01a582SDag-Erling Smørgrav lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
1297ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
1298ed01a582SDag-Erling Smørgrav GetFragmentPtr(lnk, &fptr);
1299ed01a582SDag-Erling Smørgrav SetFragmentPtr(lnk, NULL);
1300ed01a582SDag-Erling Smørgrav SetExpire(lnk, 0); /* Deletes link */
1301ccd57eeaSPaolo Pisati } else
1302ccd57eeaSPaolo Pisati fptr = NULL;
13033b160b8bSBrian Somers
1304ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
13053b160b8bSBrian Somers return (fptr);
13063b160b8bSBrian Somers }
13073b160b8bSBrian Somers
13083b160b8bSBrian Somers void
LibAliasFragmentIn(struct libalias * la,void * ptr,void * ptr_fragment)1309effc8e57SLutz Donnerhacke LibAliasFragmentIn(struct libalias *la,
1310effc8e57SLutz Donnerhacke void *ptr, /* Points to correctly de-aliased header fragment */
1311effc8e57SLutz Donnerhacke void *ptr_fragment /* fragment which must be de-aliased */
13123b160b8bSBrian Somers )
13133b160b8bSBrian Somers {
13143b160b8bSBrian Somers struct ip *pip;
13153b160b8bSBrian Somers struct ip *fpip;
13163b160b8bSBrian Somers
1317ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1318ed01a582SDag-Erling Smørgrav (void)la;
13193b160b8bSBrian Somers pip = (struct ip *)ptr;
13203b160b8bSBrian Somers fpip = (struct ip *)ptr_fragment;
13213b160b8bSBrian Somers
13223b160b8bSBrian Somers DifferentialChecksum(&fpip->ip_sum,
13232871c501SDag-Erling Smørgrav &pip->ip_dst, &fpip->ip_dst, 2);
13243b160b8bSBrian Somers fpip->ip_dst = pip->ip_dst;
1325ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
13263b160b8bSBrian Somers }
13273b160b8bSBrian Somers
1328ccd57eeaSPaolo Pisati /* Local prototypes */
1329ccd57eeaSPaolo Pisati static int
1330bc596e56SAlex Richardson LibAliasOutLocked(struct libalias *la, struct ip *pip,
1331ccd57eeaSPaolo Pisati int maxpacketsize, int create);
1332ccd57eeaSPaolo Pisati static int
1333bc596e56SAlex Richardson LibAliasInLocked(struct libalias *la, struct ip *pip,
1334ccd57eeaSPaolo Pisati int maxpacketsize);
13353b160b8bSBrian Somers
13363b160b8bSBrian Somers int
LibAliasIn(struct libalias * la,void * ptr,int maxpacketsize)1337bc596e56SAlex Richardson LibAliasIn(struct libalias *la, void *ptr, int maxpacketsize)
13383b160b8bSBrian Somers {
1339ccd57eeaSPaolo Pisati int res;
1340ccd57eeaSPaolo Pisati
1341ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1342bc596e56SAlex Richardson res = LibAliasInLocked(la, (struct ip *)ptr, maxpacketsize);
1343ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
1344ccd57eeaSPaolo Pisati return (res);
1345ccd57eeaSPaolo Pisati }
1346ccd57eeaSPaolo Pisati
1347ccd57eeaSPaolo Pisati static int
LibAliasInLocked(struct libalias * la,struct ip * pip,int maxpacketsize)1348bc596e56SAlex Richardson LibAliasInLocked(struct libalias *la, struct ip *pip, int maxpacketsize)
1349ccd57eeaSPaolo Pisati {
13503b160b8bSBrian Somers struct in_addr alias_addr;
13513b160b8bSBrian Somers int iresult;
13523b160b8bSBrian Somers
13535e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
13545e289f9eSPoul-Henning Kamp la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1355bc596e56SAlex Richardson iresult = LibAliasOutLocked(la, pip, maxpacketsize, 1);
13565e289f9eSPoul-Henning Kamp la->packetAliasMode |= PKT_ALIAS_REVERSE;
1357ccd57eeaSPaolo Pisati goto getout;
13580622eafcSBrian Somers }
13595e289f9eSPoul-Henning Kamp HouseKeeping(la);
13603b160b8bSBrian Somers alias_addr = pip->ip_dst;
13613b160b8bSBrian Somers
13628ddc51bcSEivind Eklund /* Defense against mangled packets */
13638ddc51bcSEivind Eklund if (ntohs(pip->ip_len) > maxpacketsize
1364ccd57eeaSPaolo Pisati || (pip->ip_hl << 2) > maxpacketsize) {
1365ccd57eeaSPaolo Pisati iresult = PKT_ALIAS_IGNORED;
1366ccd57eeaSPaolo Pisati goto getout;
1367ccd57eeaSPaolo Pisati }
13688ddc51bcSEivind Eklund
1369461e6f23SMaxim Sobolev if (FRAG_NO_HDR(pip)) {
1370461e6f23SMaxim Sobolev iresult = FragmentIn(la, pip->ip_src, pip, pip->ip_id,
1371461e6f23SMaxim Sobolev &pip->ip_sum);
1372461e6f23SMaxim Sobolev goto getout;
1373461e6f23SMaxim Sobolev }
1374461e6f23SMaxim Sobolev
13753b160b8bSBrian Somers iresult = PKT_ALIAS_IGNORED;
1376f0f93429SDag-Erling Smørgrav switch (pip->ip_p) {
13773b160b8bSBrian Somers case IPPROTO_ICMP:
13785e289f9eSPoul-Henning Kamp iresult = IcmpAliasIn(la, pip);
13793b160b8bSBrian Somers break;
13803b160b8bSBrian Somers case IPPROTO_UDP:
13815e289f9eSPoul-Henning Kamp iresult = UdpAliasIn(la, pip);
13823b160b8bSBrian Somers break;
13833b160b8bSBrian Somers case IPPROTO_TCP:
13845e289f9eSPoul-Henning Kamp iresult = TcpAliasIn(la, pip);
13853b160b8bSBrian Somers break;
138637ce2656SPaolo Pisati #ifdef _KERNEL
138737ce2656SPaolo Pisati case IPPROTO_SCTP:
138837ce2656SPaolo Pisati iresult = SctpAlias(la, pip, SN_TO_LOCAL);
138937ce2656SPaolo Pisati break;
139037ce2656SPaolo Pisati #endif
1391be4f3cd0SPaolo Pisati case IPPROTO_GRE: {
1392be4f3cd0SPaolo Pisati int error;
1393be4f3cd0SPaolo Pisati struct alias_data ad = {
1394be4f3cd0SPaolo Pisati .lnk = NULL,
1395be4f3cd0SPaolo Pisati .oaddr = NULL,
1396be4f3cd0SPaolo Pisati .aaddr = NULL,
1397be4f3cd0SPaolo Pisati .aport = NULL,
1398be4f3cd0SPaolo Pisati .sport = NULL,
1399be4f3cd0SPaolo Pisati .dport = NULL,
1400be4f3cd0SPaolo Pisati .maxpktsize = 0
1401be4f3cd0SPaolo Pisati };
1402be4f3cd0SPaolo Pisati
1403be4f3cd0SPaolo Pisati /* Walk out chain. */
1404be4f3cd0SPaolo Pisati error = find_handler(IN, IP, la, pip, &ad);
1405be4f3cd0SPaolo Pisati if (error == 0)
140603453c5eSRuslan Ermilov iresult = PKT_ALIAS_OK;
140703453c5eSRuslan Ermilov else
1408ab0fcfd0SPaolo Pisati iresult = ProtoAliasIn(la, pip->ip_src,
1409bc596e56SAlex Richardson pip, pip->ip_p, &pip->ip_sum);
141055a39fc5SRuslan Ermilov break;
1411effc8e57SLutz Donnerhacke }
141280607605SRuslan Ermilov default:
1413bc596e56SAlex Richardson iresult = ProtoAliasIn(la, pip->ip_src, pip,
1414ab0fcfd0SPaolo Pisati pip->ip_p, &pip->ip_sum);
14157d96f4efSBrian Somers break;
14163b160b8bSBrian Somers }
14173b160b8bSBrian Somers
1418461e6f23SMaxim Sobolev if (MF_ISSET(pip)) {
1419ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
14203b160b8bSBrian Somers
1421ed01a582SDag-Erling Smørgrav lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id);
1422ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
14233b160b8bSBrian Somers iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
1424ed01a582SDag-Erling Smørgrav SetFragmentAddr(lnk, pip->ip_dst);
1425f0f93429SDag-Erling Smørgrav } else {
14263b160b8bSBrian Somers iresult = PKT_ALIAS_ERROR;
14273b160b8bSBrian Somers }
14283b160b8bSBrian Somers }
14293b160b8bSBrian Somers
1430ccd57eeaSPaolo Pisati getout:
14313b160b8bSBrian Somers return (iresult);
14323b160b8bSBrian Somers }
14333b160b8bSBrian Somers
14343b160b8bSBrian Somers /* Unregistered address ranges */
14353b160b8bSBrian Somers
14363b160b8bSBrian Somers /* 10.0.0.0 -> 10.255.255.255 */
14373b160b8bSBrian Somers #define UNREG_ADDR_A_LOWER 0x0a000000
14383b160b8bSBrian Somers #define UNREG_ADDR_A_UPPER 0x0affffff
14393b160b8bSBrian Somers
14403b160b8bSBrian Somers /* 172.16.0.0 -> 172.31.255.255 */
14413b160b8bSBrian Somers #define UNREG_ADDR_B_LOWER 0xac100000
14423b160b8bSBrian Somers #define UNREG_ADDR_B_UPPER 0xac1fffff
14433b160b8bSBrian Somers
14443b160b8bSBrian Somers /* 192.168.0.0 -> 192.168.255.255 */
14453b160b8bSBrian Somers #define UNREG_ADDR_C_LOWER 0xc0a80000
14463b160b8bSBrian Somers #define UNREG_ADDR_C_UPPER 0xc0a8ffff
14473b160b8bSBrian Somers
144875b89337SAlexander V. Chernikov /* 100.64.0.0 -> 100.127.255.255 (RFC 6598 - Carrier Grade NAT) */
144975b89337SAlexander V. Chernikov #define UNREG_ADDR_CGN_LOWER 0x64400000
145075b89337SAlexander V. Chernikov #define UNREG_ADDR_CGN_UPPER 0x647fffff
145175b89337SAlexander V. Chernikov
14523b160b8bSBrian Somers int
LibAliasOut(struct libalias * la,void * ptr,int maxpacketsize)1453bc596e56SAlex Richardson LibAliasOut(struct libalias *la, void *ptr, int maxpacketsize)
14543b160b8bSBrian Somers {
1455ccd57eeaSPaolo Pisati int res;
1456ccd57eeaSPaolo Pisati
1457ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1458bc596e56SAlex Richardson res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, 1);
1459ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
1460ccd57eeaSPaolo Pisati return (res);
1461e6bbb691SPoul-Henning Kamp }
1462e6bbb691SPoul-Henning Kamp
1463e6bbb691SPoul-Henning Kamp int
LibAliasOutTry(struct libalias * la,void * ptr,int maxpacketsize,int create)1464bc596e56SAlex Richardson LibAliasOutTry(struct libalias *la, void *ptr, int maxpacketsize, int create)
1465ccd57eeaSPaolo Pisati {
1466ccd57eeaSPaolo Pisati int res;
1467ccd57eeaSPaolo Pisati
1468ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1469bc596e56SAlex Richardson res = LibAliasOutLocked(la, (struct ip *)ptr, maxpacketsize, create);
1470ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
1471ccd57eeaSPaolo Pisati return (res);
1472ccd57eeaSPaolo Pisati }
1473ccd57eeaSPaolo Pisati
1474ccd57eeaSPaolo Pisati static int
LibAliasOutLocked(struct libalias * la,struct ip * pip,int maxpacketsize,int create)1475effc8e57SLutz Donnerhacke LibAliasOutLocked(struct libalias *la,
1476effc8e57SLutz Donnerhacke struct ip *pip, /* valid IP packet */
1477effc8e57SLutz Donnerhacke int maxpacketsize, /* How much the packet data may grow (FTP and IRC inline changes) */
1478e6bbb691SPoul-Henning Kamp int create /* Create new entries ? */
1479e6bbb691SPoul-Henning Kamp )
1480e6bbb691SPoul-Henning Kamp {
14813b160b8bSBrian Somers int iresult;
14823b160b8bSBrian Somers struct in_addr addr_save;
14833b160b8bSBrian Somers
14845e289f9eSPoul-Henning Kamp if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
14855e289f9eSPoul-Henning Kamp la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
1486bc596e56SAlex Richardson iresult = LibAliasInLocked(la, pip, maxpacketsize);
14875e289f9eSPoul-Henning Kamp la->packetAliasMode |= PKT_ALIAS_REVERSE;
1488ccd57eeaSPaolo Pisati goto getout;
14890622eafcSBrian Somers }
14905e289f9eSPoul-Henning Kamp HouseKeeping(la);
14913b160b8bSBrian Somers
14928ddc51bcSEivind Eklund /* Defense against mangled packets */
14938ddc51bcSEivind Eklund if (ntohs(pip->ip_len) > maxpacketsize
1494ccd57eeaSPaolo Pisati || (pip->ip_hl << 2) > maxpacketsize) {
1495ccd57eeaSPaolo Pisati iresult = PKT_ALIAS_IGNORED;
1496ccd57eeaSPaolo Pisati goto getout;
1497ccd57eeaSPaolo Pisati }
14988ddc51bcSEivind Eklund
14995e289f9eSPoul-Henning Kamp addr_save = GetDefaultAliasAddress(la);
150075b89337SAlexander V. Chernikov if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY ||
150175b89337SAlexander V. Chernikov la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN) {
1502483d2f22SRuslan Ermilov u_long addr;
15033b160b8bSBrian Somers int iclass;
15043b160b8bSBrian Somers
15053b160b8bSBrian Somers iclass = 0;
15063b160b8bSBrian Somers addr = ntohl(pip->ip_src.s_addr);
15073b160b8bSBrian Somers if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
15083b160b8bSBrian Somers iclass = 3;
15093b160b8bSBrian Somers else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
15103b160b8bSBrian Somers iclass = 2;
15113b160b8bSBrian Somers else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
15123b160b8bSBrian Somers iclass = 1;
151375b89337SAlexander V. Chernikov else if (addr >= UNREG_ADDR_CGN_LOWER && addr <= UNREG_ADDR_CGN_UPPER &&
151475b89337SAlexander V. Chernikov la->packetAliasMode & PKT_ALIAS_UNREGISTERED_CGN)
151575b89337SAlexander V. Chernikov iclass = 4;
15163b160b8bSBrian Somers
1517f0f93429SDag-Erling Smørgrav if (iclass == 0) {
15185e289f9eSPoul-Henning Kamp SetDefaultAliasAddress(la, pip->ip_src);
15193b160b8bSBrian Somers }
1520f0f93429SDag-Erling Smørgrav } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) {
15215e289f9eSPoul-Henning Kamp SetDefaultAliasAddress(la, pip->ip_src);
1522ada24e69SRuslan Ermilov }
1523461e6f23SMaxim Sobolev
1524461e6f23SMaxim Sobolev if (FRAG_NO_HDR(pip)) {
1525461e6f23SMaxim Sobolev iresult = FragmentOut(la, pip, &pip->ip_sum);
1526461e6f23SMaxim Sobolev goto getout_restore;
1527461e6f23SMaxim Sobolev }
1528461e6f23SMaxim Sobolev
15293b160b8bSBrian Somers iresult = PKT_ALIAS_IGNORED;
1530f0f93429SDag-Erling Smørgrav switch (pip->ip_p) {
15313b160b8bSBrian Somers case IPPROTO_ICMP:
1532e6bbb691SPoul-Henning Kamp iresult = IcmpAliasOut(la, pip, create);
15333b160b8bSBrian Somers break;
15343b160b8bSBrian Somers case IPPROTO_UDP:
1535ea29dd92SAlexander Motin iresult = UdpAliasOut(la, pip, maxpacketsize, create);
15363b160b8bSBrian Somers break;
15373b160b8bSBrian Somers case IPPROTO_TCP:
1538e6bbb691SPoul-Henning Kamp iresult = TcpAliasOut(la, pip, maxpacketsize, create);
15393b160b8bSBrian Somers break;
154037ce2656SPaolo Pisati #ifdef _KERNEL
154137ce2656SPaolo Pisati case IPPROTO_SCTP:
154237ce2656SPaolo Pisati iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
154337ce2656SPaolo Pisati break;
154437ce2656SPaolo Pisati #endif
1545be4f3cd0SPaolo Pisati case IPPROTO_GRE: {
1546be4f3cd0SPaolo Pisati int error;
1547be4f3cd0SPaolo Pisati struct alias_data ad = {
1548be4f3cd0SPaolo Pisati .lnk = NULL,
1549be4f3cd0SPaolo Pisati .oaddr = NULL,
1550be4f3cd0SPaolo Pisati .aaddr = NULL,
1551be4f3cd0SPaolo Pisati .aport = NULL,
1552be4f3cd0SPaolo Pisati .sport = NULL,
1553be4f3cd0SPaolo Pisati .dport = NULL,
1554be4f3cd0SPaolo Pisati .maxpktsize = 0
1555be4f3cd0SPaolo Pisati };
1556be4f3cd0SPaolo Pisati /* Walk out chain. */
1557be4f3cd0SPaolo Pisati error = find_handler(OUT, IP, la, pip, &ad);
1558be4f3cd0SPaolo Pisati if (error == 0)
155903453c5eSRuslan Ermilov iresult = PKT_ALIAS_OK;
156003453c5eSRuslan Ermilov else
1561bc596e56SAlex Richardson iresult = ProtoAliasOut(la, pip,
1562ab0fcfd0SPaolo Pisati pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
156303453c5eSRuslan Ermilov break;
1564effc8e57SLutz Donnerhacke }
156580607605SRuslan Ermilov default:
1566bc596e56SAlex Richardson iresult = ProtoAliasOut(la, pip,
1567ab0fcfd0SPaolo Pisati pip->ip_dst, pip->ip_p, &pip->ip_sum, create);
15687d96f4efSBrian Somers break;
15693b160b8bSBrian Somers }
15703b160b8bSBrian Somers
1571461e6f23SMaxim Sobolev getout_restore:
15725e289f9eSPoul-Henning Kamp SetDefaultAliasAddress(la, addr_save);
1573ccd57eeaSPaolo Pisati getout:
15743b160b8bSBrian Somers return (iresult);
15753b160b8bSBrian Somers }
1576642e43b3SArchie Cobbs
1577642e43b3SArchie Cobbs int
LibAliasUnaliasOut(struct libalias * la,void * ptr,int maxpacketsize)1578effc8e57SLutz Donnerhacke LibAliasUnaliasOut(struct libalias *la,
1579effc8e57SLutz Donnerhacke void *ptr, /* valid IP packet */
1580642e43b3SArchie Cobbs int maxpacketsize /* for error checking */
1581642e43b3SArchie Cobbs )
1582642e43b3SArchie Cobbs {
1583642e43b3SArchie Cobbs struct ip *pip;
1584642e43b3SArchie Cobbs struct icmp *ic;
1585642e43b3SArchie Cobbs struct udphdr *ud;
1586642e43b3SArchie Cobbs struct tcphdr *tc;
1587ed01a582SDag-Erling Smørgrav struct alias_link *lnk;
1588642e43b3SArchie Cobbs int iresult = PKT_ALIAS_IGNORED;
1589642e43b3SArchie Cobbs
1590ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
1591642e43b3SArchie Cobbs pip = (struct ip *)ptr;
1592642e43b3SArchie Cobbs
1593642e43b3SArchie Cobbs /* Defense against mangled packets */
1594642e43b3SArchie Cobbs if (ntohs(pip->ip_len) > maxpacketsize
1595642e43b3SArchie Cobbs || (pip->ip_hl << 2) > maxpacketsize)
1596ccd57eeaSPaolo Pisati goto getout;
1597642e43b3SArchie Cobbs
15989fa0fd26SDag-Erling Smørgrav ud = (struct udphdr *)ip_next(pip);
15999fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
16009fa0fd26SDag-Erling Smørgrav ic = (struct icmp *)ip_next(pip);
1601642e43b3SArchie Cobbs
1602642e43b3SArchie Cobbs /* Find a link */
1603*fb2ea26fSMark Johnston if (pip->ip_p == IPPROTO_UDP) {
1604*fb2ea26fSMark Johnston iresult = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1605642e43b3SArchie Cobbs ud->uh_dport, ud->uh_sport,
1606*fb2ea26fSMark Johnston IPPROTO_UDP, 0, &lnk);
1607*fb2ea26fSMark Johnston if (iresult != PKT_ALIAS_OK)
1608*fb2ea26fSMark Johnston goto getout;
1609*fb2ea26fSMark Johnston } else if (pip->ip_p == IPPROTO_TCP) {
1610*fb2ea26fSMark Johnston iresult = FindUdpTcpIn(la, pip->ip_dst, pip->ip_src,
1611642e43b3SArchie Cobbs tc->th_dport, tc->th_sport,
1612*fb2ea26fSMark Johnston IPPROTO_TCP, 0, &lnk);
1613*fb2ea26fSMark Johnston if (iresult != PKT_ALIAS_OK)
1614*fb2ea26fSMark Johnston goto getout;
1615*fb2ea26fSMark Johnston } else if (pip->ip_p == IPPROTO_ICMP) {
1616*fb2ea26fSMark Johnston iresult = FindIcmpIn(la, pip->ip_dst, pip->ip_src,
1617*fb2ea26fSMark Johnston ic->icmp_id, 0, &lnk);
1618*fb2ea26fSMark Johnston if (iresult != PKT_ALIAS_OK)
1619*fb2ea26fSMark Johnston goto getout;
1620*fb2ea26fSMark Johnston } else
1621ed01a582SDag-Erling Smørgrav lnk = NULL;
1622642e43b3SArchie Cobbs
1623642e43b3SArchie Cobbs /* Change it from an aliased packet to an unaliased packet */
1624ed01a582SDag-Erling Smørgrav if (lnk != NULL) {
1625f0f93429SDag-Erling Smørgrav if (pip->ip_p == IPPROTO_UDP || pip->ip_p == IPPROTO_TCP) {
1626642e43b3SArchie Cobbs int accumulate;
1627642e43b3SArchie Cobbs struct in_addr original_address;
1628642e43b3SArchie Cobbs u_short original_port;
1629642e43b3SArchie Cobbs
1630ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
1631ed01a582SDag-Erling Smørgrav original_port = GetOriginalPort(lnk);
1632642e43b3SArchie Cobbs
1633642e43b3SArchie Cobbs /* Adjust TCP/UDP checksum */
16342871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_src);
16352871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
1636642e43b3SArchie Cobbs
1637642e43b3SArchie Cobbs if (pip->ip_p == IPPROTO_UDP) {
1638642e43b3SArchie Cobbs accumulate += ud->uh_sport;
1639642e43b3SArchie Cobbs accumulate -= original_port;
164071593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ud->uh_sum);
1641642e43b3SArchie Cobbs } else {
1642642e43b3SArchie Cobbs accumulate += tc->th_sport;
1643642e43b3SArchie Cobbs accumulate -= original_port;
164471593f95SBrian Somers ADJUST_CHECKSUM(accumulate, tc->th_sum);
1645642e43b3SArchie Cobbs }
1646642e43b3SArchie Cobbs
1647642e43b3SArchie Cobbs /* Adjust IP checksum */
1648642e43b3SArchie Cobbs DifferentialChecksum(&pip->ip_sum,
16492871c501SDag-Erling Smørgrav &original_address, &pip->ip_src, 2);
1650642e43b3SArchie Cobbs
1651642e43b3SArchie Cobbs /* Un-alias source address and port number */
1652642e43b3SArchie Cobbs pip->ip_src = original_address;
1653642e43b3SArchie Cobbs if (pip->ip_p == IPPROTO_UDP)
1654642e43b3SArchie Cobbs ud->uh_sport = original_port;
1655642e43b3SArchie Cobbs else
1656642e43b3SArchie Cobbs tc->th_sport = original_port;
1657642e43b3SArchie Cobbs
1658642e43b3SArchie Cobbs iresult = PKT_ALIAS_OK;
1659642e43b3SArchie Cobbs } else if (pip->ip_p == IPPROTO_ICMP) {
1660642e43b3SArchie Cobbs int accumulate;
1661642e43b3SArchie Cobbs struct in_addr original_address;
1662642e43b3SArchie Cobbs u_short original_id;
1663642e43b3SArchie Cobbs
1664ed01a582SDag-Erling Smørgrav original_address = GetOriginalAddress(lnk);
1665ed01a582SDag-Erling Smørgrav original_id = GetOriginalPort(lnk);
1666642e43b3SArchie Cobbs
1667642e43b3SArchie Cobbs /* Adjust ICMP checksum */
16682871c501SDag-Erling Smørgrav accumulate = twowords(&pip->ip_src);
16692871c501SDag-Erling Smørgrav accumulate -= twowords(&original_address);
1670642e43b3SArchie Cobbs accumulate += ic->icmp_id;
1671642e43b3SArchie Cobbs accumulate -= original_id;
167271593f95SBrian Somers ADJUST_CHECKSUM(accumulate, ic->icmp_cksum);
1673642e43b3SArchie Cobbs
1674642e43b3SArchie Cobbs /* Adjust IP checksum */
1675642e43b3SArchie Cobbs DifferentialChecksum(&pip->ip_sum,
16762871c501SDag-Erling Smørgrav &original_address, &pip->ip_src, 2);
1677642e43b3SArchie Cobbs
1678642e43b3SArchie Cobbs /* Un-alias source address and port number */
1679642e43b3SArchie Cobbs pip->ip_src = original_address;
1680642e43b3SArchie Cobbs ic->icmp_id = original_id;
1681642e43b3SArchie Cobbs
1682642e43b3SArchie Cobbs iresult = PKT_ALIAS_OK;
1683642e43b3SArchie Cobbs }
1684642e43b3SArchie Cobbs }
1685ccd57eeaSPaolo Pisati getout:
1686ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
1687642e43b3SArchie Cobbs return (iresult);
1688642e43b3SArchie Cobbs }
1689be4f3cd0SPaolo Pisati
1690be4f3cd0SPaolo Pisati #ifndef _KERNEL
1691be4f3cd0SPaolo Pisati
1692be4f3cd0SPaolo Pisati int
LibAliasRefreshModules(void)1693be4f3cd0SPaolo Pisati LibAliasRefreshModules(void)
1694be4f3cd0SPaolo Pisati {
1695be4f3cd0SPaolo Pisati char buf[256], conf[] = "/etc/libalias.conf";
1696be4f3cd0SPaolo Pisati FILE *fd;
16975910c1c1SPaolo Pisati int i, len;
1698be4f3cd0SPaolo Pisati
1699be4f3cd0SPaolo Pisati fd = fopen(conf, "r");
1700be4f3cd0SPaolo Pisati if (fd == NULL)
1701be4f3cd0SPaolo Pisati err(1, "fopen(%s)", conf);
1702be4f3cd0SPaolo Pisati
1703be4f3cd0SPaolo Pisati LibAliasUnLoadAllModule();
1704be4f3cd0SPaolo Pisati
1705be4f3cd0SPaolo Pisati for (;;) {
1706be4f3cd0SPaolo Pisati fgets(buf, 256, fd);
170703bc210eSDmitry Morozovsky if (feof(fd))
1708be4f3cd0SPaolo Pisati break;
1709be4f3cd0SPaolo Pisati len = strlen(buf);
1710be4f3cd0SPaolo Pisati if (len > 1) {
17115910c1c1SPaolo Pisati for (i = 0; i < len; i++)
17125910c1c1SPaolo Pisati if (!isspace(buf[i]))
17135910c1c1SPaolo Pisati break;
17145910c1c1SPaolo Pisati if (buf[i] == '#')
17155910c1c1SPaolo Pisati continue;
1716be4f3cd0SPaolo Pisati buf[len - 1] = '\0';
1717be4f3cd0SPaolo Pisati LibAliasLoadModule(buf);
1718be4f3cd0SPaolo Pisati }
1719be4f3cd0SPaolo Pisati }
1720621882f0SChristian Brueffer fclose(fd);
1721be4f3cd0SPaolo Pisati return (0);
1722be4f3cd0SPaolo Pisati }
1723be4f3cd0SPaolo Pisati
1724be4f3cd0SPaolo Pisati int
LibAliasLoadModule(char * path)1725be4f3cd0SPaolo Pisati LibAliasLoadModule(char *path)
1726be4f3cd0SPaolo Pisati {
1727be4f3cd0SPaolo Pisati struct dll *t;
1728be4f3cd0SPaolo Pisati void *handle;
1729be4f3cd0SPaolo Pisati struct proto_handler *m;
1730be4f3cd0SPaolo Pisati const char *error;
1731be4f3cd0SPaolo Pisati moduledata_t *p;
1732be4f3cd0SPaolo Pisati
1733be4f3cd0SPaolo Pisati handle = dlopen (path, RTLD_LAZY);
1734be4f3cd0SPaolo Pisati if (!handle) {
17355910c1c1SPaolo Pisati fprintf(stderr, "%s\n", dlerror());
1736be4f3cd0SPaolo Pisati return (EINVAL);
1737be4f3cd0SPaolo Pisati }
1738be4f3cd0SPaolo Pisati
1739be4f3cd0SPaolo Pisati p = dlsym(handle, "alias_mod");
1740be4f3cd0SPaolo Pisati if ((error = dlerror()) != NULL) {
17415910c1c1SPaolo Pisati fprintf(stderr, "%s\n", dlerror());
1742be4f3cd0SPaolo Pisati return (EINVAL);
1743be4f3cd0SPaolo Pisati }
1744be4f3cd0SPaolo Pisati
1745be4f3cd0SPaolo Pisati t = malloc(sizeof(struct dll));
1746be4f3cd0SPaolo Pisati if (t == NULL)
1747be4f3cd0SPaolo Pisati return (ENOMEM);
1748be4f3cd0SPaolo Pisati strncpy(t->name, p->name, DLL_LEN);
1749be4f3cd0SPaolo Pisati t->handle = handle;
1750be4f3cd0SPaolo Pisati if (attach_dll(t) == EEXIST) {
1751be4f3cd0SPaolo Pisati free(t);
17525910c1c1SPaolo Pisati fprintf(stderr, "dll conflict\n");
1753be4f3cd0SPaolo Pisati return (EEXIST);
1754be4f3cd0SPaolo Pisati }
1755be4f3cd0SPaolo Pisati
1756be4f3cd0SPaolo Pisati m = dlsym(t->handle, "handlers");
1757be4f3cd0SPaolo Pisati if ((error = dlerror()) != NULL) {
17585910c1c1SPaolo Pisati fprintf(stderr, "%s\n", error);
1759be4f3cd0SPaolo Pisati return (EINVAL);
1760be4f3cd0SPaolo Pisati }
1761be4f3cd0SPaolo Pisati
1762be4f3cd0SPaolo Pisati LibAliasAttachHandlers(m);
1763be4f3cd0SPaolo Pisati return (0);
1764be4f3cd0SPaolo Pisati }
1765be4f3cd0SPaolo Pisati
1766be4f3cd0SPaolo Pisati int
LibAliasUnLoadAllModule(void)1767be4f3cd0SPaolo Pisati LibAliasUnLoadAllModule(void)
1768be4f3cd0SPaolo Pisati {
1769be4f3cd0SPaolo Pisati struct dll *t;
1770be4f3cd0SPaolo Pisati struct proto_handler *p;
1771be4f3cd0SPaolo Pisati
1772be4f3cd0SPaolo Pisati /* Unload all modules then reload everything. */
1773be4f3cd0SPaolo Pisati while ((p = first_handler()) != NULL) {
1774ec5df3a7SGleb Smirnoff LibAliasDetachHandlers(p);
1775be4f3cd0SPaolo Pisati }
1776be4f3cd0SPaolo Pisati while ((t = walk_dll_chain()) != NULL) {
1777be4f3cd0SPaolo Pisati dlclose(t->handle);
1778be4f3cd0SPaolo Pisati free(t);
1779be4f3cd0SPaolo Pisati }
1780be4f3cd0SPaolo Pisati return (1);
1781be4f3cd0SPaolo Pisati }
1782be4f3cd0SPaolo Pisati
1783be4f3cd0SPaolo Pisati #endif
1784e876228eSPaolo Pisati
1785e876228eSPaolo Pisati #ifdef _KERNEL
1786e876228eSPaolo Pisati /*
1787ccd57eeaSPaolo Pisati * m_megapullup() - this function is a big hack.
1788ccd57eeaSPaolo Pisati * Thankfully, it's only used in ng_nat and ipfw+nat.
1789e876228eSPaolo Pisati *
1790efc66711SAlexander Motin * It allocates an mbuf with cluster and copies the specified part of the chain
1791efc66711SAlexander Motin * into cluster, so that it is all contiguous and can be accessed via a plain
1792efc66711SAlexander Motin * (char *) pointer. This is required, because libalias doesn't know how to
1793efc66711SAlexander Motin * handle mbuf chains.
1794e876228eSPaolo Pisati *
1795efc66711SAlexander Motin * On success, m_megapullup returns an mbuf (possibly with cluster) containing
1796efc66711SAlexander Motin * the input packet, on failure NULL. The input packet is always consumed.
1797e876228eSPaolo Pisati */
1798e876228eSPaolo Pisati struct mbuf *
m_megapullup(struct mbuf * m,int len)1799eb548a1aSAndrey V. Elsukov m_megapullup(struct mbuf *m, int len)
1800eb548a1aSAndrey V. Elsukov {
1801e876228eSPaolo Pisati struct mbuf *mcl;
1802e876228eSPaolo Pisati
1803efc66711SAlexander Motin if (len > m->m_pkthdr.len)
1804e876228eSPaolo Pisati goto bad;
1805e876228eSPaolo Pisati
18067525c481SGleb Smirnoff if (m->m_next == NULL && M_WRITABLE(m))
1807efc66711SAlexander Motin return (m);
1808efc66711SAlexander Motin
1809eb548a1aSAndrey V. Elsukov if (len <= MJUMPAGESIZE)
18107525c481SGleb Smirnoff mcl = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR);
1811eb548a1aSAndrey V. Elsukov else if (len <= MJUM9BYTES)
1812eb548a1aSAndrey V. Elsukov mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1813eb548a1aSAndrey V. Elsukov else if (len <= MJUM16BYTES)
1814eb548a1aSAndrey V. Elsukov mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
1815eb548a1aSAndrey V. Elsukov else
1816eb548a1aSAndrey V. Elsukov goto bad;
1817efc66711SAlexander Motin if (mcl == NULL)
1818e876228eSPaolo Pisati goto bad;
18197525c481SGleb Smirnoff m_align(mcl, len);
1820e876228eSPaolo Pisati m_move_pkthdr(mcl, m);
1821efc66711SAlexander Motin m_copydata(m, 0, len, mtod(mcl, caddr_t));
1822efc66711SAlexander Motin mcl->m_len = mcl->m_pkthdr.len = len;
1823e876228eSPaolo Pisati m_freem(m);
1824e876228eSPaolo Pisati
1825e876228eSPaolo Pisati return (mcl);
1826e876228eSPaolo Pisati bad:
1827e876228eSPaolo Pisati m_freem(m);
1828e876228eSPaolo Pisati return (NULL);
1829e876228eSPaolo Pisati }
1830e876228eSPaolo Pisati #endif
1831