2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 2001 Charles Mott <cmott@scientech.com>
24 * All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * $FreeBSD: src/lib/libalias/alias_db.c,v 1.21.2.12 2001/08/21 03:50:25 brian Exp $
52 Alias_db.c encapsulates all data structures used for storing
53 packet aliasing data. Other parts of the aliasing software
54 access data through functions provided in this file.
56 Data storage is based on the notion of a "link", which is
57 established for ICMP echo/reply packets, UDP datagrams and
58 TCP stream connections. A link stores the original source
59 and destination addresses. For UDP and TCP, it also stores
60 source and destination port numbers, as well as an alias
61 port number. Links are also used to store information about
64 There is a facility for sweeping through and deleting old
65 links as new packets are sent through. A simple timeout is
66 used for ICMP and UDP links. TCP links are left alone unless
67 there is an incomplete connection, in which case the link
68 can be deleted after a certain amount of time.
71 Initial version: August, 1996 (cjm)
73 Version 1.4: September 16, 1996 (cjm)
74 Facility for handling incoming links added.
76 Version 1.6: September 18, 1996 (cjm)
77 ICMP data handling simplified.
79 Version 1.7: January 9, 1997 (cjm)
80 Fragment handling simplified.
81 Saves pointers for unresolved fragments.
82 Permits links for unspecified remote ports
83 or unspecified remote addresses.
84 Fixed bug which did not properly zero port
85 table entries after a link was deleted.
86 Cleaned up some obsolete comments.
88 Version 1.8: January 14, 1997 (cjm)
89 Fixed data type error in StartPoint().
90 (This error did not exist prior to v1.7
91 and was discovered and fixed by Ari Suutari)
93 Version 1.9: February 1, 1997
94 Optionally, connections initiated from packet aliasing host
95 machine will will not have their port number aliased unless it
96 conflicts with an aliasing port already being used. (cjm)
98 All options earlier being #ifdef'ed are now available through
99 a new interface, SetPacketAliasMode(). This allows run time
100 control (which is now available in PPP+pktAlias through the
101 'alias' keyword). (ee)
103 Added ability to create an alias port without
104 either destination address or port specified.
105 port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
107 Removed K&R style function headers
108 and general cleanup. (ee)
110 Added packetAliasMode to replace compiler #defines's (ee)
112 Allocates sockets for partially specified
113 ports if ALIAS_USE_SOCKETS defined. (cjm)
115 Version 2.0: March, 1997
116 SetAliasAddress() will now clean up alias links
117 if the aliasing address is changed. (cjm)
119 PacketAliasPermanentLink() function added to support permanent
120 links. (J. Fortes suggested the need for this.)
123 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
125 (192.168.0.2, port 21) <-> alias port 3604, known dest addr
128 These permanent links allow for incoming connections to
129 machines on the local network. They can be given with a
130 user-chosen amount of specificity, with increasing specificity
131 meaning more security. (cjm)
133 Quite a bit of rework to the basic engine. The portTable[]
134 array, which kept track of which ports were in use was replaced
135 by a table/linked list structure. (cjm)
137 SetExpire() function added. (cjm)
139 DeleteLink() no longer frees memory association with a pointer
140 to a fragment (this bug was first recognized by E. Eklund in
143 Version 2.1: May, 1997 (cjm)
144 Packet aliasing engine reworked so that it can handle
145 multiple external addresses rather than just a single
148 PacketAliasRedirectPort() and PacketAliasRedirectAddr()
149 added to the API. The first function is a more generalized
150 version of PacketAliasPermanentLink(). The second function
151 implements static network address translation.
153 Version 3.2: July, 2000 (salander and satoh)
154 Added FindNewPortGroup to get contiguous range of port values.
156 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing
157 link but not actually add one.
159 Added FindRtspOut, which is closely derived from FindUdpTcpOut,
160 except that the alias port (from FindNewPortGroup) is provided
163 See HISTORY file for additional revisions.
167 /* System include files */
174 #include <sys/queue.h>
175 #include <sys/socket.h>
176 #include <sys/time.h>
177 #include <sys/types.h>
179 /* BSD network include files */
180 #include <netinet/in_systm.h>
181 #include <netinet/in.h>
182 #include <netinet/ip.h>
183 #include <netinet/tcp.h>
184 #include <arpa/inet.h>
187 #include "alias_local.h"
192 Constants (note: constants are also defined
193 near relevant functions or structs)
196 /* Sizes of input and output link tables */
197 #define LINK_TABLE_OUT_SIZE 101
198 #define LINK_TABLE_IN_SIZE 4001
200 /* Parameters used for cleanup of expired links */
201 #define ALIAS_CLEANUP_INTERVAL_SECS 60
202 #define ALIAS_CLEANUP_MAX_SPOKES 30
204 /* Timeouts (in seconds) for different link types */
205 #define ICMP_EXPIRE_TIME 60
206 #define UDP_EXPIRE_TIME 60
207 #define PROTO_EXPIRE_TIME 60
208 #define FRAGMENT_ID_EXPIRE_TIME 10
209 #define FRAGMENT_PTR_EXPIRE_TIME 30
211 /* TCP link expire time for different cases */
212 /* When the link has been used and closed - minimal grace time to
213 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
214 #ifndef TCP_EXPIRE_DEAD
215 # define TCP_EXPIRE_DEAD 10
218 /* When the link has been used and closed on one side - the other side
219 is allowed to still send data */
220 #ifndef TCP_EXPIRE_SINGLEDEAD
221 # define TCP_EXPIRE_SINGLEDEAD 90
224 /* When the link isn't yet up */
225 #ifndef TCP_EXPIRE_INITIAL
226 # define TCP_EXPIRE_INITIAL 300
229 /* When the link is up */
230 #ifndef TCP_EXPIRE_CONNECTED
231 # define TCP_EXPIRE_CONNECTED 86400
235 static int iChatAVHack
= 1;
238 /* Dummy port number codes used for FindLinkIn/Out() and AddLink().
239 These constants can be anything except zero, which indicates an
240 unknown port number. */
242 #define NO_DEST_PORT 1
243 #define NO_SRC_PORT 1
249 The fundamental data structure used in this program is
250 "struct alias_link". Whenever a TCP connection is made,
251 a UDP datagram is sent out, or an ICMP echo request is made,
252 a link record is made (if it has not already been created).
253 The link record is identified by the source address/port
254 and the destination address/port. In the case of an ICMP
255 echo request, the source port is treated as being equivalent
256 with the 16-bit ID number of the ICMP packet.
258 The link record also can store some auxiliary data. For
259 TCP connections that have had sequence and acknowledgment
260 modifications, data space is available to track these changes.
261 A state field is used to keep track in changes to the TCP
262 connection state. ID numbers of fragments can also be
263 stored in the auxiliary space. Pointers to unresolved
264 fragments can also be stored.
266 The link records support two independent chainings. Lookup
267 tables for input and out tables hold the initial pointers
268 the link chains. On input, the lookup table indexes on alias
269 port and link type. On output, the lookup table indexes on
270 source address, destination address, source port, destination
274 struct ack_data_record
/* used to save changes to ACK/sequence numbers */
282 struct tcp_state
/* Information about TCP connection */
284 int in
; /* State for outside -> inside */
285 int out
; /* State for inside -> outside */
286 int index
; /* Index to ACK data array */
287 int ack_modified
; /* Indicates whether ACK and sequence numbers */
291 #define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes
292 saved for a modified TCP stream */
295 struct tcp_state state
;
296 struct ack_data_record ack
[N_LINK_TCP_DATA
];
297 int fwhole
; /* Which firewall record is used for this hole? */
300 struct server
/* LSNAT server pool (circular list) */
307 struct alias_link
/* Main data structure */
309 struct in_addr src_addr
; /* Address and port information */
310 struct in_addr dst_addr
;
311 struct in_addr alias_addr
;
312 struct in_addr proxy_addr
;
317 struct server
*server
;
319 int link_type
; /* Type of link: TCP, UDP, ICMP, proto, frag */
321 /* values for link_type */
322 #define LINK_ICMP IPPROTO_ICMP
323 #define LINK_UDP IPPROTO_UDP
324 #define LINK_TCP IPPROTO_TCP
325 #define LINK_FRAGMENT_ID (IPPROTO_MAX + 1)
326 #define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2)
327 #define LINK_ADDR (IPPROTO_MAX + 3)
328 #define LINK_PPTP (IPPROTO_MAX + 4)
330 int flags
; /* indicates special characteristics */
333 #define LINK_UNKNOWN_DEST_PORT 0x01
334 #define LINK_UNKNOWN_DEST_ADDR 0x02
335 #define LINK_PERMANENT 0x04
336 #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
337 #define LINK_UNFIREWALLED 0x08
338 #define LINK_LAST_LINE_CRLF_TERMED 0x10
339 #define LINK_CONE 0x20
341 int timestamp
; /* Time link was last accessed */
342 int expire_time
; /* Expire time for link */
344 int sockfd
; /* socket descriptor */
346 LIST_ENTRY(alias_link
) list_out
; /* Linked list of pointers for */
347 LIST_ENTRY(alias_link
) list_in
; /* input and output lookup tables */
349 union /* Auxiliary data */
352 struct in_addr frag_addr
;
363 The global variables listed here are only accessed from
364 within alias_db.c and so are prefixed with the static
368 int packetAliasMode
; /* Mode flags */
369 /* - documented in alias.h */
371 static struct in_addr aliasAddress
; /* Address written onto source */
372 /* field of IP packet. */
374 static struct in_addr targetAddress
; /* IP address incoming packets */
375 /* are sent to if no aliasing */
376 /* link already exists */
378 static struct in_addr nullAddress
; /* Used as a dummy parameter for */
379 /* some function calls */
380 static LIST_HEAD(, alias_link
)
381 linkTableOut
[LINK_TABLE_OUT_SIZE
]; /* Lookup table of pointers to */
382 /* chains of link records. Each */
383 static LIST_HEAD(, alias_link
) /* link record is doubly indexed */
384 linkTableIn
[LINK_TABLE_IN_SIZE
]; /* into input and output lookup */
387 static int icmpLinkCount
; /* Link statistics */
388 static int udpLinkCount
;
389 static int tcpLinkCount
;
390 static int pptpLinkCount
;
391 static int protoLinkCount
;
392 static int fragmentIdLinkCount
;
393 static int fragmentPtrLinkCount
;
394 static int sockCount
;
396 static int cleanupIndex
; /* Index to chain of link table */
397 /* being inspected for old links */
399 static int timeStamp
; /* System time in seconds for */
402 static int lastCleanupTime
; /* Last time IncrementalCleanup() */
405 static int houseKeepingResidual
; /* used by HouseKeeping() */
407 static int deleteAllLinks
; /* If equal to zero, DeleteLink() */
408 /* will not remove permanent links */
410 static FILE *monitorFile
; /* File descriptor for link */
411 /* statistics monitoring file */
413 static int newDefaultLink
; /* Indicates if a new aliasing */
414 /* link has been created after a */
415 /* call to PacketAliasIn/Out(). */
418 static int fireWallFD
= -1; /* File descriptor to be able to */
419 /* control firewall. Opened by */
420 /* PacketAliasSetMode on first */
421 /* setting the PKT_ALIAS_PUNCH_FW */
431 /* Internal utility routines (used only in alias_db.c)
433 Lookup table starting points:
434 StartPointIn() -- link table initial search point for
436 StartPointOut() -- link table initial search point for
440 SeqDiff() -- difference between two TCP sequences
441 ShowAliasStats() -- send alias statistics to a monitor file
445 /* Local prototypes */
446 static u_int
StartPointIn(struct in_addr
, u_short
, int);
448 static u_int
StartPointOut(struct in_addr
, struct in_addr
,
449 u_short
, u_short
, int);
451 static int SeqDiff(u_long
, u_long
);
453 static void ShowAliasStats(void);
456 /* Firewall control */
457 static void InitPunchFW(void);
458 static void UninitPunchFW(void);
459 static void ClearFWHole(struct alias_link
*link
);
462 /* Log file control */
463 static void InitPacketAliasLog(void);
464 static void UninitPacketAliasLog(void);
467 StartPointIn(struct in_addr alias_addr
,
473 n
= alias_addr
.s_addr
;
474 if (link_type
!= LINK_PPTP
)
477 return(n
% LINK_TABLE_IN_SIZE
);
482 StartPointOut(struct in_addr src_addr
, struct in_addr dst_addr
,
483 u_short src_port
, u_short dst_port
, int link_type
)
488 n
+= dst_addr
.s_addr
;
489 if (link_type
!= LINK_PPTP
) {
495 return(n
% LINK_TABLE_OUT_SIZE
);
500 SeqDiff(u_long x
, u_long y
)
502 /* Return the difference between two TCP sequence numbers */
505 This function is encapsulated in case there are any unusual
506 arithmetic conditions that need to be considered.
509 return (ntohl(y
) - ntohl(x
));
516 /* Used for debugging */
520 fprintf(monitorFile
, "icmp=%d, udp=%d, tcp=%d, pptp=%d, proto=%d, frag_id=%d frag_ptr=%d",
527 fragmentPtrLinkCount
);
529 fprintf(monitorFile
, " / tot=%d (sock=%d)\n",
530 icmpLinkCount
+ udpLinkCount
534 + fragmentIdLinkCount
535 + fragmentPtrLinkCount
,
546 /* Internal routines for finding, deleting and adding links
549 GetNewPort() -- find and reserve new alias port number
550 GetSocket() -- try to allocate a socket for a given port
552 Link creation and deletion:
553 CleanupAliasData() - remove all link chains from lookup table
554 IncrementalCleanup() - look for stale links in a single chain
555 DeleteLink() - remove link
557 ReLink() - change link
560 FindLinkOut() - find link for outgoing packets
561 FindLinkIn() - find link for incoming packets
564 FindNewPortGroup() - find an available group of ports
567 /* Local prototypes */
568 static int GetNewPort(struct alias_link
*, int);
570 static u_short
GetSocket(u_short
, int *, int);
572 static void CleanupAliasData(void);
574 static void IncrementalCleanup(void);
576 static void DeleteLink(struct alias_link
*);
578 static struct alias_link
*
579 AddLink(struct in_addr
, struct in_addr
, struct in_addr
,
580 u_short
, u_short
, int, int);
582 static struct alias_link
*
583 ReLink(struct alias_link
*,
584 struct in_addr
, struct in_addr
, struct in_addr
,
585 u_short
, u_short
, int, int);
587 static struct alias_link
*
588 FindLinkOut(struct in_addr
, struct in_addr
, u_short
, u_short
, int, int);
590 static struct alias_link
*
591 FindLinkIn(struct in_addr
, struct in_addr
, u_short
, u_short
, int, int);
594 #define ALIAS_PORT_BASE 0x08000
595 #define ALIAS_PORT_MASK 0x07fff
596 #define ALIAS_PORT_MASK_EVEN 0x07ffe
597 #define GET_NEW_PORT_MAX_ATTEMPTS 20
599 #define GET_ALIAS_PORT -1
600 #define GET_ALIAS_EPHEMERAL_PORT -2
601 #define GET_ALIAS_ID GET_ALIAS_PORT
603 #define FIND_EVEN_ALIAS_BASE 1
605 /* GetNewPort() allocates port numbers. Note that if a port number
606 is already in use, that does not mean that it cannot be used by
607 another link concurrently. This is because GetNewPort() looks for
608 unused triplets: (dest addr, dest port, alias port). */
611 GetEphemeralPort(struct alias_link
*link
)
615 /* Port number search */
616 for (i
=0; i
< GET_NEW_PORT_MAX_ATTEMPTS
; i
++)
618 struct sockaddr_in sock_addr
;
621 struct alias_link
*search_result
;
623 if (GetSocket(0, &link
->sockfd
, link
->link_type
) == 0)
625 salen
= sizeof(struct sockaddr_in
);
626 if (getsockname(link
->sockfd
, (struct sockaddr
*)&sock_addr
, &salen
) == -1)
628 port_net
= sock_addr
.sin_port
;
630 search_result
= FindLinkIn(link
->dst_addr
, link
->alias_addr
,
631 link
->dst_port
, port_net
,
634 if (search_result
== NULL
) {
635 link
->alias_port
= port_net
;
642 fprintf(stderr
, "PacketAlias/GetEphemeralPort(): ");
643 fprintf(stderr
, "could not find free port\n");
650 GetNewPort(struct alias_link
*link
, int alias_port_param
)
657 if (alias_port_param
== GET_ALIAS_EPHEMERAL_PORT
)
658 return GetEphemeralPort(link
);
661 Description of alias_port_param for GetNewPort(). When
662 this parameter is zero or positive, it precisely specifies
663 the port number. GetNewPort() will return this number
664 without check that it is in use.
666 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
667 selected port number.
669 if (alias_port_param
== GET_ALIAS_PORT
)
672 * The aliasing port is automatically selected
673 * by one of two methods below:
675 max_trials
= GET_NEW_PORT_MAX_ATTEMPTS
;
677 if (packetAliasMode
& PKT_ALIAS_SAME_PORTS
)
680 * When the PKT_ALIAS_SAME_PORTS option is
681 * chosen, the first try will be the
682 * actual source port. If this is already
683 * in use, the remainder of the trials
686 port_net
= link
->src_port
;
687 port_sys
= ntohs(port_net
);
691 /* First trial and all subsequent are random. */
692 port_sys
= random() & ALIAS_PORT_MASK
;
693 port_sys
+= ALIAS_PORT_BASE
;
694 port_net
= htons(port_sys
);
697 else if (alias_port_param
>= 0 && alias_port_param
< 0x10000)
699 link
->alias_port
= (u_short
) alias_port_param
;
705 fprintf(stderr
, "PacketAlias/GetNewPort(): ");
706 fprintf(stderr
, "input parameter error\n");
712 /* Port number search */
713 for (i
=0; i
<max_trials
; i
++)
716 struct alias_link
*search_result
;
718 search_result
= FindLinkIn(link
->dst_addr
, link
->alias_addr
,
719 link
->dst_port
, port_net
,
722 if (search_result
== NULL
)
724 else if (!(link
->flags
& LINK_PARTIALLY_SPECIFIED
)
725 && (search_result
->flags
& LINK_PARTIALLY_SPECIFIED
))
732 if ((packetAliasMode
& PKT_ALIAS_USE_SOCKETS
)
733 && (link
->flags
& LINK_PARTIALLY_SPECIFIED
)
734 && ((link
->link_type
== LINK_TCP
) ||
735 (link
->link_type
== LINK_UDP
)))
737 if (GetSocket(port_net
, &link
->sockfd
, link
->link_type
))
739 link
->alias_port
= port_net
;
745 link
->alias_port
= port_net
;
750 port_sys
= random() & ALIAS_PORT_MASK
;
751 port_sys
+= ALIAS_PORT_BASE
;
752 port_net
= htons(port_sys
);
755 fprintf(stderr
, "PacketAlias/GetnewPort(): ");
756 fprintf(stderr
, "could not find free port\n");
764 GetSocket(u_short port_net
, int *sockfd
, int link_type
)
768 struct sockaddr_in sock_addr
;
770 if (link_type
== LINK_TCP
)
771 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
772 else if (link_type
== LINK_UDP
)
773 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
777 fprintf(stderr
, "PacketAlias/GetSocket(): ");
778 fprintf(stderr
, "incorrect link type\n");
786 fprintf(stderr
, "PacketAlias/GetSocket(): ");
787 fprintf(stderr
, "socket() error %d\n", *sockfd
);
792 sock_addr
.sin_family
= AF_INET
;
793 sock_addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
794 sock_addr
.sin_port
= port_net
;
797 (struct sockaddr
*) &sock_addr
,
813 /* FindNewPortGroup() returns a base port number for an available
814 range of contiguous port numbers. Note that if a port number
815 is already in use, that does not mean that it cannot be used by
816 another link concurrently. This is because FindNewPortGroup()
817 looks for unused triplets: (dest addr, dest port, alias port). */
820 FindNewPortGroup(struct in_addr dst_addr
,
821 struct in_addr alias_addr
,
834 * Get link_type from protocol
840 link_type
= LINK_UDP
;
843 link_type
= LINK_TCP
;
851 * The aliasing port is automatically selected
852 * by one of two methods below:
854 max_trials
= GET_NEW_PORT_MAX_ATTEMPTS
;
856 if (packetAliasMode
& PKT_ALIAS_SAME_PORTS
) {
858 * When the ALIAS_SAME_PORTS option is
859 * chosen, the first try will be the
860 * actual source port. If this is already
861 * in use, the remainder of the trials
864 port_sys
= ntohs(src_port
);
868 /* First trial and all subsequent are random. */
869 if (align
== FIND_EVEN_ALIAS_BASE
)
870 port_sys
= random() & ALIAS_PORT_MASK_EVEN
;
872 port_sys
= random() & ALIAS_PORT_MASK
;
874 port_sys
+= ALIAS_PORT_BASE
;
877 /* Port number search */
878 for (i
= 0; i
< max_trials
; i
++) {
880 struct alias_link
*search_result
;
882 for (j
= 0; j
< port_count
; j
++)
883 if (0 != (search_result
= FindLinkIn(dst_addr
, alias_addr
,
884 dst_port
, htons(port_sys
+ j
),
888 /* Found a good range, return base */
890 return (htons(port_sys
));
892 /* Find a new base to try */
893 if (align
== FIND_EVEN_ALIAS_BASE
)
894 port_sys
= random() & ALIAS_PORT_MASK_EVEN
;
896 port_sys
= random() & ALIAS_PORT_MASK
;
898 port_sys
+= ALIAS_PORT_BASE
;
902 fprintf(stderr
, "PacketAlias/FindNewPortGroup(): ");
903 fprintf(stderr
, "could not find free port(s)\n");
910 CleanupAliasData(void)
912 struct alias_link
*link
;
916 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
918 link
= LIST_FIRST(&linkTableOut
[i
]);
921 struct alias_link
*link_next
;
922 link_next
= LIST_NEXT(link
, list_out
);
934 IncrementalCleanup(void)
937 struct alias_link
*link
;
940 link
= LIST_FIRST(&linkTableOut
[cleanupIndex
++]);
944 struct alias_link
*link_next
;
946 link_next
= LIST_NEXT(link
, list_out
);
947 idelta
= timeStamp
- link
->timestamp
;
948 switch (link
->link_type
)
951 if (idelta
> link
->expire_time
)
953 struct tcp_dat
*tcp_aux
;
955 tcp_aux
= link
->data
.tcp
;
956 if (tcp_aux
->state
.in
!= ALIAS_TCP_STATE_CONNECTED
957 || tcp_aux
->state
.out
!= ALIAS_TCP_STATE_CONNECTED
)
965 if (idelta
> link
->expire_time
)
975 if (cleanupIndex
== LINK_TABLE_OUT_SIZE
)
980 DeleteLink(struct alias_link
*link
)
983 /* Don't do anything if the link is marked permanent */
984 if (deleteAllLinks
== 0 && link
->flags
& LINK_PERMANENT
)
988 /* Delete associated firewall hole, if any */
992 /* Free memory allocated for LSNAT server pool */
993 if (link
->server
!= NULL
) {
994 struct server
*head
, *curr
, *next
;
996 head
= curr
= link
->server
;
1000 } while ((curr
= next
) != head
);
1003 /* Adjust output table pointers */
1004 LIST_REMOVE(link
, list_out
);
1006 /* Adjust input table pointers */
1007 LIST_REMOVE(link
, list_in
);
1009 /* Close socket, if one has been allocated */
1010 if (link
->sockfd
!= -1)
1013 close(link
->sockfd
);
1016 /* Link-type dependent cleanup */
1017 switch(link
->link_type
)
1027 free(link
->data
.tcp
);
1032 case LINK_FRAGMENT_ID
:
1033 fragmentIdLinkCount
--;
1035 case LINK_FRAGMENT_PTR
:
1036 fragmentPtrLinkCount
--;
1037 if (link
->data
.frag_ptr
!= NULL
)
1038 free(link
->data
.frag_ptr
);
1048 if ((packetAliasMode
& PKT_ALIAS_LOG
) != 0 &&
1049 !IN_MULTICAST(link
->src_addr
.s_addr
) &&
1050 !IN_MULTICAST(link
->dst_addr
.s_addr
))
1056 switch(link
->link_type
)
1067 fprintf(monitorFile
, "Deleted%s %s:%d<->%s:%d to %s:%d<->%s:%d\n",
1069 inet_ntop(AF_INET
, &link
->src_addr
, src
, sizeof(src
)), link
->src_port
,
1070 inet_ntop(AF_INET
, &link
->dst_addr
, dst
, sizeof(dst
)), link
->dst_port
,
1071 inet_ntop(AF_INET
, &link
->alias_addr
, alias
, sizeof(alias
)), link
->alias_port
,
1072 dst
, link
->dst_port
);
1073 fflush(monitorFile
);
1076 if (packetAliasMode
& PKT_ALIAS_LOG
)
1085 static struct alias_link
*
1086 AddLink(struct in_addr src_addr
,
1087 struct in_addr dst_addr
,
1088 struct in_addr alias_addr
,
1091 int alias_port_param
, /* if less than zero, alias */
1092 int link_type
) /* port will be automatically */
1093 { /* chosen. If greater than */
1094 u_int start_point
; /* zero, equal to alias port */
1095 struct alias_link
*link
;
1097 link
= malloc(sizeof(struct alias_link
));
1100 /* Basic initialization */
1101 link
->src_addr
= src_addr
;
1102 link
->dst_addr
= dst_addr
;
1103 link
->alias_addr
= alias_addr
;
1104 link
->proxy_addr
.s_addr
= INADDR_ANY
;
1105 link
->src_port
= src_port
;
1106 link
->dst_port
= dst_port
;
1107 link
->proxy_port
= 0;
1108 link
->server
= NULL
;
1109 link
->link_type
= link_type
;
1112 link
->timestamp
= timeStamp
;
1114 /* Expiration time */
1118 link
->expire_time
= ICMP_EXPIRE_TIME
;
1121 if (dst_addr
.s_addr
== 0 && dst_port
== 0)
1122 link
->expire_time
= UDP_EXPIRE_TIME
* 5;
1124 link
->expire_time
= UDP_EXPIRE_TIME
;
1127 link
->expire_time
= TCP_EXPIRE_INITIAL
;
1130 link
->flags
|= LINK_PERMANENT
; /* no timeout. */
1132 case LINK_FRAGMENT_ID
:
1133 link
->expire_time
= FRAGMENT_ID_EXPIRE_TIME
;
1135 case LINK_FRAGMENT_PTR
:
1136 link
->expire_time
= FRAGMENT_PTR_EXPIRE_TIME
;
1141 link
->expire_time
= PROTO_EXPIRE_TIME
;
1145 /* Determine alias flags */
1146 if (dst_addr
.s_addr
== INADDR_ANY
)
1147 link
->flags
|= LINK_UNKNOWN_DEST_ADDR
;
1149 link
->flags
|= LINK_UNKNOWN_DEST_PORT
;
1151 /* Determine alias port */
1152 if (GetNewPort(link
, alias_port_param
) != 0)
1157 /* Link-type dependent initialization */
1160 struct tcp_dat
*aux_tcp
;
1169 aux_tcp
= malloc(sizeof(struct tcp_dat
));
1170 if (aux_tcp
!= NULL
)
1175 aux_tcp
->state
.in
= ALIAS_TCP_STATE_NOT_CONNECTED
;
1176 aux_tcp
->state
.out
= ALIAS_TCP_STATE_NOT_CONNECTED
;
1177 aux_tcp
->state
.index
= 0;
1178 aux_tcp
->state
.ack_modified
= 0;
1179 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
1180 aux_tcp
->ack
[i
].active
= 0;
1181 aux_tcp
->fwhole
= -1;
1182 link
->data
.tcp
= aux_tcp
;
1187 fprintf(stderr
, "PacketAlias/AddLink: ");
1188 fprintf(stderr
, " cannot allocate auxiliary TCP data\n");
1197 case LINK_FRAGMENT_ID
:
1198 fragmentIdLinkCount
++;
1200 case LINK_FRAGMENT_PTR
:
1201 fragmentPtrLinkCount
++;
1210 /* Set up pointers for output lookup table */
1211 start_point
= StartPointOut(src_addr
, dst_addr
,
1212 src_port
, dst_port
, link_type
);
1213 LIST_INSERT_HEAD(&linkTableOut
[start_point
], link
, list_out
);
1215 /* Set up pointers for input lookup table */
1216 start_point
= StartPointIn(alias_addr
, link
->alias_port
, link_type
);
1217 LIST_INSERT_HEAD(&linkTableIn
[start_point
], link
, list_in
);
1222 fprintf(stderr
, "PacketAlias/AddLink(): ");
1223 fprintf(stderr
, "malloc() call failed.\n");
1228 if ((packetAliasMode
& PKT_ALIAS_LOG
) != 0 &&
1229 !IN_MULTICAST(link
->src_addr
.s_addr
) &&
1230 !IN_MULTICAST(link
->dst_addr
.s_addr
))
1236 switch(link
->link_type
)
1247 fprintf(monitorFile
, "Added %s %s:%d<->%s:%d to %s:%d<->%s:%d\n",
1249 inet_ntop(AF_INET
, &link
->src_addr
, src
, sizeof(src
)), link
->src_port
,
1250 inet_ntop(AF_INET
, &link
->dst_addr
, dst
, sizeof(dst
)), link
->dst_port
,
1251 inet_ntop(AF_INET
, &link
->alias_addr
, alias
, sizeof(alias
)), link
->alias_port
,
1252 dst
, link
->dst_port
);
1255 if (packetAliasMode
& PKT_ALIAS_LOG
)
1262 static struct alias_link
*
1263 ReLink(struct alias_link
*old_link
,
1264 struct in_addr src_addr
,
1265 struct in_addr dst_addr
,
1266 struct in_addr alias_addr
,
1269 int alias_port_param
, /* if less than zero, alias */
1270 int link_type
) /* port will be automatically */
1271 { /* chosen. If greater than */
1272 struct alias_link
*new_link
; /* zero, equal to alias port */
1274 new_link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1275 src_port
, dst_port
, alias_port_param
,
1278 if (new_link
!= NULL
&&
1279 old_link
->link_type
== LINK_TCP
&&
1280 old_link
->data
.tcp
->fwhole
> 0) {
1281 PunchFWHole(new_link
);
1284 if ((old_link
->flags
& LINK_CONE
) == 0)
1285 DeleteLink(old_link
);
1289 static struct alias_link
*
1290 _FindLinkOut(struct in_addr src_addr
,
1291 struct in_addr dst_addr
,
1295 int replace_partial_links
)
1298 struct alias_link
*link
;
1300 i
= StartPointOut(src_addr
, dst_addr
, src_port
, dst_port
, link_type
);
1301 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1303 if (link
->src_addr
.s_addr
== src_addr
.s_addr
1304 && link
->server
== NULL
1305 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
1306 && link
->dst_port
== dst_port
1307 && link
->src_port
== src_port
1308 && link
->link_type
== link_type
)
1310 link
->timestamp
= timeStamp
;
1315 /* Search for partially specified links. */
1316 if (link
== NULL
&& replace_partial_links
)
1318 if (dst_port
!= 0 && dst_addr
.s_addr
!= INADDR_ANY
)
1320 link
= _FindLinkOut(src_addr
, dst_addr
, src_port
, 0,
1323 link
= _FindLinkOut(src_addr
, nullAddress
, src_port
,
1324 dst_port
, link_type
, 0);
1327 (dst_port
!= 0 || dst_addr
.s_addr
!= INADDR_ANY
))
1329 link
= _FindLinkOut(src_addr
, nullAddress
, src_port
, 0,
1335 src_addr
, dst_addr
, link
->alias_addr
,
1336 src_port
, dst_port
, link
->alias_port
,
1344 static struct alias_link
*
1345 FindLinkOut(struct in_addr src_addr
,
1346 struct in_addr dst_addr
,
1350 int replace_partial_links
)
1352 struct alias_link
*link
;
1354 link
= _FindLinkOut(src_addr
, dst_addr
, src_port
, dst_port
,
1355 link_type
, replace_partial_links
);
1359 /* The following allows permanent links to be
1360 specified as using the default source address
1361 (i.e. device interface address) without knowing
1362 in advance what that address is. */
1363 if (aliasAddress
.s_addr
!= 0 &&
1364 src_addr
.s_addr
== aliasAddress
.s_addr
)
1366 link
= _FindLinkOut(nullAddress
, dst_addr
, src_port
, dst_port
,
1367 link_type
, replace_partial_links
);
1375 static struct alias_link
*
1376 _FindLinkIn(struct in_addr dst_addr
,
1377 struct in_addr alias_addr
,
1381 int replace_partial_links
)
1385 struct alias_link
*link
;
1386 struct alias_link
*link_fully_specified
;
1387 struct alias_link
*link_unknown_all
;
1388 struct alias_link
*link_unknown_dst_addr
;
1389 struct alias_link
*link_unknown_dst_port
;
1391 /* Initialize pointers */
1392 link_fully_specified
= NULL
;
1393 link_unknown_all
= NULL
;
1394 link_unknown_dst_addr
= NULL
;
1395 link_unknown_dst_port
= NULL
;
1397 /* If either the dest addr or port is unknown, the search
1398 loop will have to know about this. */
1401 if (dst_addr
.s_addr
== INADDR_ANY
)
1402 flags_in
|= LINK_UNKNOWN_DEST_ADDR
;
1404 flags_in
|= LINK_UNKNOWN_DEST_PORT
;
1407 start_point
= StartPointIn(alias_addr
, alias_port
, link_type
);
1408 LIST_FOREACH(link
, &linkTableIn
[start_point
], list_in
)
1412 flags
= flags_in
| link
->flags
;
1413 if (!(flags
& LINK_PARTIALLY_SPECIFIED
))
1415 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1416 && link
->alias_port
== alias_port
1417 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
1418 && link
->dst_port
== dst_port
1419 && link
->link_type
== link_type
)
1421 link_fully_specified
= link
;
1425 else if ((flags
& LINK_UNKNOWN_DEST_ADDR
)
1426 && (flags
& LINK_UNKNOWN_DEST_PORT
))
1428 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1429 && link
->alias_port
== alias_port
1430 && link
->link_type
== link_type
)
1432 if (link_unknown_all
== NULL
)
1433 link_unknown_all
= link
;
1436 else if (flags
& LINK_UNKNOWN_DEST_ADDR
)
1438 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1439 && link
->alias_port
== alias_port
1440 && link
->link_type
== link_type
1441 && link
->dst_port
== dst_port
)
1443 if (link_unknown_dst_addr
== NULL
)
1444 link_unknown_dst_addr
= link
;
1447 else if (flags
& LINK_UNKNOWN_DEST_PORT
)
1449 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1450 && link
->alias_port
== alias_port
1451 && link
->link_type
== link_type
1452 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
)
1454 if (link_unknown_dst_port
== NULL
)
1455 link_unknown_dst_port
= link
;
1462 if (link_fully_specified
!= NULL
)
1464 link_fully_specified
->timestamp
= timeStamp
;
1465 link
= link_fully_specified
;
1467 else if (link_unknown_dst_port
!= NULL
)
1468 link
= link_unknown_dst_port
;
1469 else if (link_unknown_dst_addr
!= NULL
)
1470 link
= link_unknown_dst_addr
;
1471 else if (link_unknown_all
!= NULL
)
1472 link
= link_unknown_all
;
1476 if (replace_partial_links
&&
1477 (link
->flags
& LINK_PARTIALLY_SPECIFIED
|| link
->server
!= NULL
))
1479 struct in_addr src_addr
;
1482 if (link
->server
!= NULL
) { /* LSNAT link */
1483 src_addr
= link
->server
->addr
;
1484 src_port
= link
->server
->port
;
1485 link
->server
= link
->server
->next
;
1487 src_addr
= link
->src_addr
;
1488 src_port
= link
->src_port
;
1492 src_addr
, dst_addr
, alias_addr
,
1493 src_port
, dst_port
, alias_port
,
1500 static struct alias_link
*
1501 FindLinkIn(struct in_addr dst_addr
,
1502 struct in_addr alias_addr
,
1506 int replace_partial_links
)
1508 struct alias_link
*link
;
1510 link
= _FindLinkIn(dst_addr
, alias_addr
, dst_port
, alias_port
,
1511 link_type
, replace_partial_links
);
1515 /* The following allows permanent links to be
1516 specified as using the default aliasing address
1517 (i.e. device interface address) without knowing
1518 in advance what that address is. */
1519 if (aliasAddress
.s_addr
!= 0 &&
1520 alias_addr
.s_addr
== aliasAddress
.s_addr
)
1522 link
= _FindLinkIn(dst_addr
, nullAddress
, dst_port
, alias_port
,
1523 link_type
, replace_partial_links
);
1533 /* External routines for finding/adding links
1535 -- "external" means outside alias_db.c, but within alias*.c --
1537 FindIcmpIn(), FindIcmpOut()
1538 FindFragmentIn1(), FindFragmentIn2()
1539 AddFragmentPtrLink(), FindFragmentPtr()
1540 FindProtoIn(), FindProtoOut()
1541 FindUdpTcpIn(), FindUdpTcpOut()
1542 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1543 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1544 FindOriginalAddress(), FindAliasAddress()
1546 (prototypes in alias_local.h)
1551 FindIcmpIn(struct in_addr dst_addr
,
1552 struct in_addr alias_addr
,
1556 struct alias_link
*link
;
1558 link
= FindLinkIn(dst_addr
, alias_addr
,
1559 NO_DEST_PORT
, id_alias
,
1561 if (link
== NULL
&& create
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1563 struct in_addr target_addr
;
1565 target_addr
= FindOriginalAddress(alias_addr
);
1566 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1567 id_alias
, NO_DEST_PORT
, id_alias
,
1576 FindIcmpOut(struct in_addr src_addr
,
1577 struct in_addr dst_addr
,
1581 struct alias_link
* link
;
1583 link
= FindLinkOut(src_addr
, dst_addr
,
1586 if (link
== NULL
&& create
)
1588 struct in_addr alias_addr
;
1590 alias_addr
= FindAliasAddress(src_addr
);
1591 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1592 id
, NO_DEST_PORT
, GET_ALIAS_ID
,
1601 FindFragmentIn1(struct in_addr dst_addr
,
1602 struct in_addr alias_addr
,
1605 struct alias_link
*link
;
1607 link
= FindLinkIn(dst_addr
, alias_addr
,
1608 NO_DEST_PORT
, ip_id
,
1609 LINK_FRAGMENT_ID
, 0);
1613 link
= AddLink(nullAddress
, dst_addr
, alias_addr
,
1614 NO_SRC_PORT
, NO_DEST_PORT
, ip_id
,
1623 FindFragmentIn2(struct in_addr dst_addr
, /* Doesn't add a link if one */
1624 struct in_addr alias_addr
, /* is not found. */
1627 return FindLinkIn(dst_addr
, alias_addr
,
1628 NO_DEST_PORT
, ip_id
,
1629 LINK_FRAGMENT_ID
, 0);
1634 AddFragmentPtrLink(struct in_addr dst_addr
,
1637 return AddLink(nullAddress
, dst_addr
, nullAddress
,
1638 NO_SRC_PORT
, NO_DEST_PORT
, ip_id
,
1644 FindFragmentPtr(struct in_addr dst_addr
,
1647 return FindLinkIn(dst_addr
, nullAddress
,
1648 NO_DEST_PORT
, ip_id
,
1649 LINK_FRAGMENT_PTR
, 0);
1654 FindProtoIn(struct in_addr dst_addr
,
1655 struct in_addr alias_addr
,
1658 struct alias_link
*link
;
1660 link
= FindLinkIn(dst_addr
, alias_addr
,
1664 if (link
== NULL
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1666 struct in_addr target_addr
;
1668 target_addr
= FindOriginalAddress(alias_addr
);
1669 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1670 NO_SRC_PORT
, NO_DEST_PORT
, 0,
1679 FindProtoOut(struct in_addr src_addr
,
1680 struct in_addr dst_addr
,
1683 struct alias_link
*link
;
1685 link
= FindLinkOut(src_addr
, dst_addr
,
1686 NO_SRC_PORT
, NO_DEST_PORT
,
1691 struct in_addr alias_addr
;
1693 alias_addr
= FindAliasAddress(src_addr
);
1694 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1695 NO_SRC_PORT
, NO_DEST_PORT
, 0,
1704 FindUdpTcpIn(struct in_addr dst_addr
,
1705 struct in_addr alias_addr
,
1712 struct alias_link
*link
;
1717 link_type
= LINK_UDP
;
1720 link_type
= LINK_TCP
;
1727 link
= FindLinkIn(dst_addr
, alias_addr
,
1728 dst_port
, alias_port
,
1731 if (link
== NULL
&& create
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1733 struct in_addr target_addr
;
1735 target_addr
= FindOriginalAddress(alias_addr
);
1736 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1737 alias_port
, dst_port
, alias_port
,
1746 FindUdpTcpOut(struct in_addr src_addr
,
1747 struct in_addr dst_addr
,
1754 struct alias_link
*link
;
1759 link_type
= LINK_UDP
;
1762 link_type
= LINK_TCP
;
1769 link
= FindLinkOut(src_addr
, dst_addr
, src_port
, dst_port
, link_type
, create
);
1771 if (link
== NULL
&& create
)
1773 struct in_addr alias_addr
;
1774 struct in_addr dst_addr2
= dst_addr
;
1775 u_short dst_port2
= dst_port
;
1777 alias_addr
= FindAliasAddress(src_addr
);
1779 if (iChatAVHack
&& link_type
== LINK_UDP
&& dst_port
== htons(5678)) {
1780 dst_addr2
.s_addr
= 0;
1783 link
= AddLink(src_addr
, dst_addr2
, alias_addr
,
1784 src_port
, dst_port2
, GET_ALIAS_PORT
,
1787 (link
->flags
& (LINK_UNKNOWN_DEST_ADDR
| LINK_UNKNOWN_DEST_PORT
)) != 0)
1789 link
->flags
|= LINK_CONE
;
1790 link
= ReLink(link
, link
->src_addr
, dst_addr
, link
->alias_addr
,
1791 link
->src_port
, dst_port
, link
->alias_port
, link_type
);
1800 AddPptp(struct in_addr src_addr
,
1801 struct in_addr dst_addr
,
1802 struct in_addr alias_addr
,
1803 u_int16_t src_call_id
)
1805 struct alias_link
*link
;
1807 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1808 src_call_id
, 0, GET_ALIAS_PORT
,
1816 FindPptpOutByCallId(struct in_addr src_addr
,
1817 struct in_addr dst_addr
,
1818 u_int16_t src_call_id
)
1821 struct alias_link
*link
;
1823 i
= StartPointOut(src_addr
, dst_addr
, 0, 0, LINK_PPTP
);
1824 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1825 if (link
->link_type
== LINK_PPTP
&&
1826 link
->src_addr
.s_addr
== src_addr
.s_addr
&&
1827 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1828 link
->src_port
== src_call_id
)
1836 FindPptpOutByPeerCallId(struct in_addr src_addr
,
1837 struct in_addr dst_addr
,
1838 u_int16_t dst_call_id
)
1841 struct alias_link
*link
;
1843 i
= StartPointOut(src_addr
, dst_addr
, 0, 0, LINK_PPTP
);
1844 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1845 if (link
->link_type
== LINK_PPTP
&&
1846 link
->src_addr
.s_addr
== src_addr
.s_addr
&&
1847 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1848 link
->dst_port
== dst_call_id
)
1856 FindPptpInByCallId(struct in_addr dst_addr
,
1857 struct in_addr alias_addr
,
1858 u_int16_t dst_call_id
)
1861 struct alias_link
*link
;
1863 i
= StartPointIn(alias_addr
, 0, LINK_PPTP
);
1864 LIST_FOREACH(link
, &linkTableIn
[i
], list_in
)
1865 if (link
->link_type
== LINK_PPTP
&&
1866 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1867 link
->alias_addr
.s_addr
== alias_addr
.s_addr
&&
1868 link
->dst_port
== dst_call_id
)
1876 FindPptpInByPeerCallId(struct in_addr dst_addr
,
1877 struct in_addr alias_addr
,
1878 u_int16_t alias_call_id
)
1880 struct alias_link
*link
;
1882 link
= FindLinkIn(dst_addr
, alias_addr
,
1883 0/* any */, alias_call_id
,
1892 FindRtspOut(struct in_addr src_addr
,
1893 struct in_addr dst_addr
,
1899 struct alias_link
*link
;
1904 link_type
= LINK_UDP
;
1907 link_type
= LINK_TCP
;
1914 link
= FindLinkOut(src_addr
, dst_addr
, src_port
, 0, link_type
, 1);
1918 struct in_addr alias_addr
;
1920 alias_addr
= FindAliasAddress(src_addr
);
1921 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1922 src_port
, 0, alias_port
,
1931 FindOriginalAddress(struct in_addr alias_addr
)
1933 struct alias_link
*link
;
1935 link
= FindLinkIn(nullAddress
, alias_addr
,
1936 0, 0, LINK_ADDR
, 0);
1940 if (targetAddress
.s_addr
== INADDR_ANY
)
1942 else if (targetAddress
.s_addr
== INADDR_NONE
)
1943 return aliasAddress
;
1945 return targetAddress
;
1949 if (link
->server
!= NULL
) { /* LSNAT link */
1950 struct in_addr src_addr
;
1952 src_addr
= link
->server
->addr
;
1953 link
->server
= link
->server
->next
;
1955 } else if (link
->src_addr
.s_addr
== INADDR_ANY
)
1956 return aliasAddress
;
1958 return link
->src_addr
;
1964 FindAliasAddress(struct in_addr original_addr
)
1966 struct alias_link
*link
;
1968 link
= FindLinkOut(original_addr
, nullAddress
,
1969 0, 0, LINK_ADDR
, 0);
1972 return aliasAddress
;
1976 if (link
->alias_addr
.s_addr
== INADDR_ANY
)
1977 return aliasAddress
;
1979 return link
->alias_addr
;
1983 /* FindAliasPortOut */
1984 /* external routine for NatPortMap */
1985 /* return alias port for the src_addr,dst_addr,src_port and proto */
1986 /* if one doesn't existed, create a mapping with providing pub_port if it's not 0 */
1987 /* delete mapping if addmapping is not true */
1989 FindAliasPortOut(struct in_addr src_addr
, struct in_addr dst_addr
, u_short src_port
, u_short pub_port
, u_char proto
, int lifetime
, char addmapping
)
1992 struct alias_link
*link
;
1998 link_type
= LINK_UDP
;
2001 link_type
= LINK_TCP
;
2012 printf("FindAliasPortOut:: srcaddr= %s:%u, ",
2013 inet_ntoa(src_addr
), ntohs(src_port
));
2014 printf("dstadd= %s:%u link_type= %d, lifetime= %d\n",
2015 inet_ntoa(dst_addr
), ntohs(pub_port
), link_type
, lifetime
);
2017 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
2019 link
= LIST_FIRST(&linkTableOut
[i
]);
2020 while (link
!= NULL
)
2022 struct alias_link
*link_next
;
2023 char src_str
[32], dst_str
[32], alias_str
[32];
2025 snprintf(src_str
, sizeof(src_str
), "%s:%u",
2026 inet_ntoa(link
->src_addr
), ntohs(link
->src_port
));
2027 snprintf(dst_str
, sizeof(dst_str
), "%s:%u",
2028 inet_ntoa(link
->dst_addr
), ntohs(link
->dst_port
));
2029 snprintf(alias_str
, sizeof(alias_str
), "%s:%u",
2030 inet_ntoa(link
->alias_addr
), ntohs(link
->alias_port
));
2032 printf(" linkTableOut[%d:%d] src= %s dst= %s alias= %s flags= 0x%x linktype= %d ts= %d exp= %d fd= %d",
2033 i
, icount
, src_str
, dst_str
, alias_str
,
2034 link
->flags
, link
->link_type
, link
->timestamp
, link
->expire_time
, link
->sockfd
);
2036 link_next
= LIST_NEXT(link
, list_out
);
2045 i
= StartPointOut(src_addr
, dst_addr
, src_port
, 0, link_type
);
2047 printf("PORTMAP::StartPointOut returns %d\n", i
);
2049 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
2051 if (link
->src_addr
.s_addr
== src_addr
.s_addr
&&
2052 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
2053 link
->src_port
== src_port
&& link
->link_type
== link_type
)
2057 if ( link
== NULL
&& addmapping
)
2059 struct in_addr alias_addr
;
2061 printf("PORTMAP:: cannot find mapping, adding mapping private port =%d, public port = %d\n",
2062 src_port
, pub_port
);
2064 /* address/port in not in list, create new mapping */
2066 alias_addr
= FindAliasAddress(src_addr
);
2067 /* create new mapping */
2068 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2069 src_port
, 0, GET_ALIAS_EPHEMERAL_PORT
,
2071 if ( link
!= NULL
) {
2072 /* link was create, set new lifetime */
2073 SetExpire(link
, lifetime
);
2074 /* Prevent link deletion when incoming connection arrive */
2075 link
->flags
|= LINK_CONE
;
2081 return( GetAliasPort(link
));
2084 SetExpire(link
, 0); /* delete mapping */
2093 /* External routines for getting or changing link data
2094 (external to alias_db.c, but internal to alias*.c)
2096 SetFragmentData(), GetFragmentData()
2097 SetFragmentPtr(), GetFragmentPtr()
2098 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
2099 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
2100 GetOriginalPort(), GetAliasPort()
2101 SetAckModified(), GetAckModified()
2102 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
2103 SetLastLineCrlfTermed(), GetLastLineCrlfTermed()
2109 SetFragmentAddr(struct alias_link
*link
, struct in_addr src_addr
)
2111 link
->data
.frag_addr
= src_addr
;
2116 GetFragmentAddr(struct alias_link
*link
, struct in_addr
*src_addr
)
2118 *src_addr
= link
->data
.frag_addr
;
2123 SetFragmentPtr(struct alias_link
*link
, char *fptr
)
2125 link
->data
.frag_ptr
= fptr
;
2130 GetFragmentPtr(struct alias_link
*link
, char **fptr
)
2132 *fptr
= link
->data
.frag_ptr
;
2137 SetStateIn(struct alias_link
*link
, int state
)
2139 /* TCP input state */
2141 case ALIAS_TCP_STATE_DISCONNECTED
:
2142 if (link
->data
.tcp
->state
.out
!= ALIAS_TCP_STATE_CONNECTED
)
2143 link
->expire_time
= TCP_EXPIRE_DEAD
;
2145 link
->expire_time
= TCP_EXPIRE_SINGLEDEAD
;
2147 case ALIAS_TCP_STATE_CONNECTED
:
2148 if (link
->data
.tcp
->state
.out
== ALIAS_TCP_STATE_CONNECTED
)
2149 link
->expire_time
= TCP_EXPIRE_CONNECTED
;
2154 link
->data
.tcp
->state
.in
= state
;
2159 SetStateOut(struct alias_link
*link
, int state
)
2161 /* TCP output state */
2163 case ALIAS_TCP_STATE_DISCONNECTED
:
2164 if (link
->data
.tcp
->state
.in
!= ALIAS_TCP_STATE_CONNECTED
)
2165 link
->expire_time
= TCP_EXPIRE_DEAD
;
2167 link
->expire_time
= TCP_EXPIRE_SINGLEDEAD
;
2169 case ALIAS_TCP_STATE_CONNECTED
:
2170 if (link
->data
.tcp
->state
.in
== ALIAS_TCP_STATE_CONNECTED
)
2171 link
->expire_time
= TCP_EXPIRE_CONNECTED
;
2176 link
->data
.tcp
->state
.out
= state
;
2181 GetStateIn(struct alias_link
*link
)
2183 /* TCP input state */
2184 return link
->data
.tcp
->state
.in
;
2189 GetStateOut(struct alias_link
*link
)
2191 /* TCP output state */
2192 return link
->data
.tcp
->state
.out
;
2197 GetOriginalAddress(struct alias_link
*link
)
2199 if (link
->src_addr
.s_addr
== INADDR_ANY
)
2200 return aliasAddress
;
2202 return(link
->src_addr
);
2207 GetDestAddress(struct alias_link
*link
)
2209 return(link
->dst_addr
);
2214 GetAliasAddress(struct alias_link
*link
)
2216 if (link
->alias_addr
.s_addr
== INADDR_ANY
)
2217 return aliasAddress
;
2219 return link
->alias_addr
;
2224 GetDefaultAliasAddress()
2226 return aliasAddress
;
2231 SetDefaultAliasAddress(struct in_addr alias_addr
)
2233 aliasAddress
= alias_addr
;
2238 GetOriginalPort(struct alias_link
*link
)
2240 return(link
->src_port
);
2245 GetAliasPort(struct alias_link
*link
)
2247 return(link
->alias_port
);
2252 GetDestPort(struct alias_link
*link
)
2254 return(link
->dst_port
);
2259 SetAckModified(struct alias_link
*link
)
2261 /* Indicate that ACK numbers have been modified in a TCP connection */
2262 link
->data
.tcp
->state
.ack_modified
= 1;
2267 GetProxyAddress(struct alias_link
*link
)
2269 return link
->proxy_addr
;
2274 SetProxyAddress(struct alias_link
*link
, struct in_addr addr
)
2276 link
->proxy_addr
= addr
;
2281 GetProxyPort(struct alias_link
*link
)
2283 return link
->proxy_port
;
2288 SetProxyPort(struct alias_link
*link
, u_short port
)
2290 link
->proxy_port
= port
;
2295 GetAckModified(struct alias_link
*link
)
2297 /* See if ACK numbers have been modified */
2298 return link
->data
.tcp
->state
.ack_modified
;
2303 GetDeltaAckIn(struct ip
*pip
, struct alias_link
*link
)
2306 Find out how much the ACK number has been altered for an incoming
2307 TCP packet. To do this, a circular list of ACK numbers where the TCP
2308 packet size was altered is searched.
2313 int delta
, ack_diff_min
;
2316 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2321 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
2323 struct ack_data_record x
;
2325 x
= link
->data
.tcp
->ack
[i
];
2330 ack_diff
= SeqDiff(x
.ack_new
, ack
);
2333 if (ack_diff_min
>= 0)
2335 if (ack_diff
< ack_diff_min
)
2338 ack_diff_min
= ack_diff
;
2344 ack_diff_min
= ack_diff
;
2354 GetDeltaSeqOut(struct ip
*pip
, struct alias_link
*link
)
2357 Find out how much the sequence number has been altered for an outgoing
2358 TCP packet. To do this, a circular list of ACK numbers where the TCP
2359 packet size was altered is searched.
2364 int delta
, seq_diff_min
;
2367 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2372 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
2374 struct ack_data_record x
;
2376 x
= link
->data
.tcp
->ack
[i
];
2381 seq_diff
= SeqDiff(x
.ack_old
, seq
);
2384 if (seq_diff_min
>= 0)
2386 if (seq_diff
< seq_diff_min
)
2389 seq_diff_min
= seq_diff
;
2395 seq_diff_min
= seq_diff
;
2405 AddSeq(struct ip
*pip
, struct alias_link
*link
, int delta
)
2408 When a TCP packet has been altered in length, save this
2409 information in a circular list. If enough packets have
2410 been altered, then this list will begin to overwrite itself.
2414 struct ack_data_record x
;
2415 int hlen
, tlen
, dlen
;
2418 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2420 hlen
= (pip
->ip_hl
+ tc
->th_off
) << 2;
2421 tlen
= ntohs(pip
->ip_len
);
2424 x
.ack_old
= htonl(ntohl(tc
->th_seq
) + dlen
);
2425 x
.ack_new
= htonl(ntohl(tc
->th_seq
) + dlen
+ delta
);
2429 i
= link
->data
.tcp
->state
.index
;
2430 link
->data
.tcp
->ack
[i
] = x
;
2433 if (i
== N_LINK_TCP_DATA
)
2434 link
->data
.tcp
->state
.index
= 0;
2436 link
->data
.tcp
->state
.index
= i
;
2440 SetExpire(struct alias_link
*link
, int expire
)
2444 link
->flags
&= ~LINK_PERMANENT
;
2447 else if (expire
== -1)
2449 link
->flags
|= LINK_PERMANENT
;
2451 else if (expire
> 0)
2453 link
->expire_time
= expire
;
2458 fprintf(stderr
, "PacketAlias/SetExpire(): ");
2459 fprintf(stderr
, "error in expire parameter\n");
2465 ClearCheckNewLink(void)
2471 SetLastLineCrlfTermed(struct alias_link
*link
, int yes
)
2475 link
->flags
|= LINK_LAST_LINE_CRLF_TERMED
;
2477 link
->flags
&= ~LINK_LAST_LINE_CRLF_TERMED
;
2481 GetLastLineCrlfTermed(struct alias_link
*link
)
2484 return (link
->flags
& LINK_LAST_LINE_CRLF_TERMED
);
2488 SetDestCallId(struct alias_link
*link
, u_int16_t cid
)
2492 link
= ReLink(link
, link
->src_addr
, link
->dst_addr
, link
->alias_addr
,
2493 link
->src_port
, cid
, link
->alias_port
, link
->link_type
);
2498 /* Miscellaneous Functions
2501 InitPacketAliasLog()
2502 UninitPacketAliasLog()
2506 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2507 is called to find and remove timed-out aliasing links. Logic exists
2508 to sweep through the entire table and linked list structure
2511 (prototype in alias_local.h)
2522 * Save system time (seconds) in global variable timeStamp for
2523 * use by other functions. This is done so as not to unnecessarily
2524 * waste timeline by making system calls.
2526 gettimeofday(&tv
, &tz
);
2527 timeStamp
= tv
.tv_sec
;
2529 /* Compute number of spokes (output table link chains) to cover */
2530 n100
= LINK_TABLE_OUT_SIZE
* 100 + houseKeepingResidual
;
2531 n100
*= timeStamp
- lastCleanupTime
;
2532 n100
/= ALIAS_CLEANUP_INTERVAL_SECS
;
2536 /* Handle different cases */
2537 if (n
> ALIAS_CLEANUP_MAX_SPOKES
)
2539 n
= ALIAS_CLEANUP_MAX_SPOKES
;
2540 lastCleanupTime
= timeStamp
;
2541 houseKeepingResidual
= 0;
2544 IncrementalCleanup();
2548 lastCleanupTime
= timeStamp
;
2549 houseKeepingResidual
= n100
- 100*n
;
2552 IncrementalCleanup();
2557 fprintf(stderr
, "PacketAlias/HouseKeeping(): ");
2558 fprintf(stderr
, "something unexpected in time values\n");
2560 lastCleanupTime
= timeStamp
;
2561 houseKeepingResidual
= 0;
2566 /* Init the log file and enable logging */
2568 InitPacketAliasLog(void)
2570 if ((~packetAliasMode
& PKT_ALIAS_LOG
)
2571 && (monitorFile
= fopen("/var/log/alias.log", "w")))
2573 packetAliasMode
|= PKT_ALIAS_LOG
;
2574 fprintf(monitorFile
,
2575 "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2580 /* Close the log-file and disable logging. */
2582 UninitPacketAliasLog(void)
2585 fclose(monitorFile
);
2588 packetAliasMode
&= ~PKT_ALIAS_LOG
;
2596 /* Outside world interfaces
2598 -- "outside world" means other than alias*.c routines --
2600 PacketAliasRedirectPort()
2601 PacketAliasAddServer()
2602 PacketAliasRedirectProto()
2603 PacketAliasRedirectAddr()
2604 PacketAliasRedirectDelete()
2605 PacketAliasSetAddress()
2608 PacketAliasSetMode()
2610 (prototypes in alias.h)
2613 /* Redirection from a specific public addr:port to a
2614 private addr:port */
2616 PacketAliasRedirectPort(struct in_addr src_addr
, u_short src_port
,
2617 struct in_addr dst_addr
, u_short dst_port
,
2618 struct in_addr alias_addr
, u_short alias_port
,
2622 struct alias_link
*link
;
2627 link_type
= LINK_UDP
;
2630 link_type
= LINK_TCP
;
2634 fprintf(stderr
, "PacketAliasRedirectPort(): ");
2635 fprintf(stderr
, "only TCP and UDP protocols allowed\n");
2640 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2641 src_port
, dst_port
, alias_port
,
2646 link
->flags
|= LINK_PERMANENT
;
2651 fprintf(stderr
, "PacketAliasRedirectPort(): "
2652 "call to AddLink() failed\n");
2659 /* Add server to the pool of servers */
2661 PacketAliasAddServer(struct alias_link
*link
, struct in_addr addr
, u_short port
)
2663 struct server
*server
;
2665 server
= malloc(sizeof(struct server
));
2667 if (server
!= NULL
) {
2668 struct server
*head
;
2670 server
->addr
= addr
;
2671 server
->port
= port
;
2673 head
= link
->server
;
2675 server
->next
= server
;
2679 for (s
= head
; s
->next
!= head
; s
= s
->next
);
2681 server
->next
= head
;
2683 link
->server
= server
;
2689 /* Redirect packets of a given IP protocol from a specific
2690 public address to a private address */
2692 PacketAliasRedirectProto(struct in_addr src_addr
,
2693 struct in_addr dst_addr
,
2694 struct in_addr alias_addr
,
2697 struct alias_link
*link
;
2699 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2700 NO_SRC_PORT
, NO_DEST_PORT
, 0,
2705 link
->flags
|= LINK_PERMANENT
;
2710 fprintf(stderr
, "PacketAliasRedirectProto(): "
2711 "call to AddLink() failed\n");
2718 /* Static address translation */
2720 PacketAliasRedirectAddr(struct in_addr src_addr
,
2721 struct in_addr alias_addr
)
2723 struct alias_link
*link
;
2725 link
= AddLink(src_addr
, nullAddress
, alias_addr
,
2731 link
->flags
|= LINK_PERMANENT
;
2736 fprintf(stderr
, "PacketAliasRedirectAddr(): "
2737 "call to AddLink() failed\n");
2746 PacketAliasRedirectDelete(struct alias_link
*link
)
2748 /* This is a dangerous function to put in the API,
2749 because an invalid pointer can crash the program. */
2758 PacketAliasSetAddress(struct in_addr addr
)
2760 if (packetAliasMode
& PKT_ALIAS_RESET_ON_ADDR_CHANGE
2761 && aliasAddress
.s_addr
!= addr
.s_addr
)
2764 aliasAddress
= addr
;
2769 PacketAliasSetTarget(struct in_addr target_addr
)
2771 targetAddress
= target_addr
;
2776 PacketAliasInit(void)
2781 static int firstCall
= 1;
2785 gettimeofday(&tv
, &tz
);
2786 timeStamp
= tv
.tv_sec
;
2787 lastCleanupTime
= tv
.tv_sec
;
2788 houseKeepingResidual
= 0;
2790 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
2791 LIST_INIT(&linkTableOut
[i
]);
2792 for (i
=0; i
<LINK_TABLE_IN_SIZE
; i
++)
2793 LIST_INIT(&linkTableIn
[i
]);
2795 atexit(PacketAliasUninit
);
2805 aliasAddress
.s_addr
= INADDR_ANY
;
2806 targetAddress
.s_addr
= INADDR_ANY
;
2813 fragmentIdLinkCount
= 0;
2814 fragmentPtrLinkCount
= 0;
2819 packetAliasMode
= PKT_ALIAS_SAME_PORTS
2820 | PKT_ALIAS_USE_SOCKETS
2821 | PKT_ALIAS_RESET_ON_ADDR_CHANGE
;
2825 PacketAliasUninit(void) {
2829 UninitPacketAliasLog();
2836 /* Change mode for some operations */
2839 unsigned int flags
, /* Which state to bring flags to */
2840 unsigned int mask
/* Mask of which flags to affect (use 0 to do a
2841 probe for flag values) */
2844 /* Enable logging? */
2845 if (flags
& mask
& PKT_ALIAS_LOG
)
2847 InitPacketAliasLog(); /* Do the enable */
2849 /* _Disable_ logging? */
2850 if (~flags
& mask
& PKT_ALIAS_LOG
) {
2851 UninitPacketAliasLog();
2855 /* Start punching holes in the firewall? */
2856 if (flags
& mask
& PKT_ALIAS_PUNCH_FW
) {
2859 /* Stop punching holes in the firewall? */
2860 if (~flags
& mask
& PKT_ALIAS_PUNCH_FW
) {
2865 /* Other flags can be set/cleared without special action */
2866 packetAliasMode
= (flags
& mask
) | (packetAliasMode
& ~mask
);
2867 return packetAliasMode
;
2872 PacketAliasCheckNewLink(void)
2874 return newDefaultLink
;
2881 Code to support firewall punching. This shouldn't really be in this
2882 file, but making variables global is evil too.
2885 /* Firewall include files */
2887 #include <netinet/ip_fw.h>
2891 static void ClearAllFWHoles(void);
2893 static int fireWallBaseNum
; /* The first firewall entry free for our use */
2894 static int fireWallNumNums
; /* How many entries can we use? */
2895 static int fireWallActiveNum
; /* Which entry did we last use? */
2896 static char *fireWallField
; /* bool array for entries */
2898 #define fw_setfield(field, num) \
2900 (field)[(num) - fireWallBaseNum] = 1; \
2901 } /*lint -save -e717 */ while(0) /*lint -restore */
2902 #define fw_clrfield(field, num) \
2904 (field)[(num) - fireWallBaseNum] = 0; \
2905 } /*lint -save -e717 */ while(0) /*lint -restore */
2906 #define fw_tstfield(field, num) ((field)[(num) - fireWallBaseNum])
2910 fireWallField
= malloc(fireWallNumNums
);
2911 if (fireWallField
) {
2912 memset(fireWallField
, 0, fireWallNumNums
);
2913 if (fireWallFD
< 0) {
2914 fireWallFD
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
2917 fireWallActiveNum
= fireWallBaseNum
;
2922 UninitPunchFW(void) {
2924 if (fireWallFD
>= 0)
2928 free(fireWallField
);
2929 fireWallField
= NULL
;
2930 packetAliasMode
&= ~PKT_ALIAS_PUNCH_FW
;
2933 /* Make a certain link go through the firewall */
2935 PunchFWHole(struct alias_link
*link
) {
2936 int r
; /* Result code */
2937 struct ip_fw rule
; /* On-the-fly built rule */
2938 int fwhole
; /* Where to punch hole */
2940 /* Don't do anything unless we are asked to */
2941 if ( !(packetAliasMode
& PKT_ALIAS_PUNCH_FW
) ||
2943 link
->link_type
!= LINK_TCP
)
2946 memset(&rule
, 0, sizeof rule
);
2950 /* Find empty slot */
2951 for (fwhole
= fireWallActiveNum
;
2952 fwhole
< fireWallBaseNum
+ fireWallNumNums
&&
2953 fw_tstfield(fireWallField
, fwhole
);
2956 if (fwhole
== fireWallBaseNum
+ fireWallNumNums
) {
2957 for (fwhole
= fireWallBaseNum
;
2958 fwhole
< fireWallActiveNum
&&
2959 fw_tstfield(fireWallField
, fwhole
);
2962 if (fwhole
== fireWallActiveNum
) {
2963 /* No rule point empty - we can't punch more holes. */
2964 fireWallActiveNum
= fireWallBaseNum
;
2966 fprintf(stderr
, "libalias: Unable to create firewall hole!\n");
2971 /* Start next search at next position */
2972 fireWallActiveNum
= fwhole
+1;
2974 /* Build generic part of the two rules */
2975 rule
.fw_number
= fwhole
;
2976 IP_FW_SETNSRCP(&rule
, 1); /* Number of source ports. */
2977 IP_FW_SETNDSTP(&rule
, 1); /* Number of destination ports. */
2978 rule
.fw_flg
= IP_FW_F_ACCEPT
| IP_FW_F_IN
| IP_FW_F_OUT
;
2979 rule
.fw_prot
= IPPROTO_TCP
;
2980 rule
.fw_smsk
.s_addr
= INADDR_BROADCAST
;
2981 rule
.fw_dmsk
.s_addr
= INADDR_BROADCAST
;
2983 /* Build and apply specific part of the rules */
2984 rule
.fw_src
= GetOriginalAddress(link
);
2985 rule
.fw_dst
= GetDestAddress(link
);
2986 rule
.fw_uar
.fw_pts
[0] = ntohs(GetOriginalPort(link
));
2987 rule
.fw_uar
.fw_pts
[1] = ntohs(GetDestPort(link
));
2989 /* Skip non-bound links - XXX should not be strictly necessary,
2990 but seems to leave hole if not done. Leak of non-bound links?
2991 (Code should be left even if the problem is fixed - it is a
2992 clear optimization) */
2993 if (rule
.fw_uar
.fw_pts
[0] != 0 && rule
.fw_uar
.fw_pts
[1] != 0) {
2994 r
= setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_ADD
, &rule
, sizeof rule
);
2997 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2999 rule
.fw_src
= GetDestAddress(link
);
3000 rule
.fw_dst
= GetOriginalAddress(link
);
3001 rule
.fw_uar
.fw_pts
[0] = ntohs(GetDestPort(link
));
3002 rule
.fw_uar
.fw_pts
[1] = ntohs(GetOriginalPort(link
));
3003 r
= setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_ADD
, &rule
, sizeof rule
);
3006 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
3009 /* Indicate hole applied */
3010 link
->data
.tcp
->fwhole
= fwhole
;
3011 fw_setfield(fireWallField
, fwhole
);
3014 /* Remove a hole in a firewall associated with a particular alias
3015 link. Calling this too often is harmless. */
3017 ClearFWHole(struct alias_link
*link
) {
3018 if (link
->link_type
== LINK_TCP
) {
3019 int fwhole
= link
->data
.tcp
->fwhole
; /* Where is the firewall hole? */
3025 memset(&rule
, 0, sizeof rule
);
3026 rule
.fw_number
= fwhole
;
3027 while (!setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_DEL
, &rule
, sizeof rule
))
3029 fw_clrfield(fireWallField
, fwhole
);
3030 link
->data
.tcp
->fwhole
= -1;
3034 /* Clear out the entire range dedicated to firewall holes. */
3036 ClearAllFWHoles(void) {
3037 struct ip_fw rule
; /* On-the-fly built rule */
3043 memset(&rule
, 0, sizeof rule
);
3044 for (i
= fireWallBaseNum
; i
< fireWallBaseNum
+ fireWallNumNums
; i
++) {
3046 while (!setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_DEL
, &rule
, sizeof rule
))
3049 memset(fireWallField
, 0, fireWallNumNums
);
3054 PacketAliasSetFWBase(unsigned int base
, unsigned int num
) {
3056 fireWallBaseNum
= base
;
3057 fireWallNumNums
= num
;
3065 struct alias_link
*link
;
3067 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
3069 link
= LIST_FIRST(&linkTableOut
[i
]);
3070 while (link
!= NULL
)
3072 struct alias_link
*link_next
;
3073 char src_str
[32], dst_str
[32], alias_str
[32];
3075 snprintf(src_str
, sizeof(src_str
), "%s:%u",
3076 inet_ntoa(link
->src_addr
), ntohs(link
->src_port
));
3077 snprintf(dst_str
, sizeof(dst_str
), "%s:%u",
3078 inet_ntoa(link
->dst_addr
), ntohs(link
->dst_port
));
3079 snprintf(alias_str
, sizeof(alias_str
), "%s:%u",
3080 inet_ntoa(link
->alias_addr
), ntohs(link
->alias_port
));
3082 syslog(LOG_ERR
, " linkTableOut[%d:%d] src= %s dst= %s alias= %s flags= 0x%x linktype= %d ts= %d exp= %d fd= %d",
3083 i
, icount
, src_str
, dst_str
, alias_str
,
3084 link
->flags
, link
->link_type
, link
->timestamp
, link
->expire_time
, link
->sockfd
);
3086 link_next
= LIST_NEXT(link
, list_out
);