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(__uint32_t
, __uint32_t
);
454 static void ShowAliasStats(void);
458 /* Firewall control */
459 static void InitPunchFW(void);
460 static void UninitPunchFW(void);
461 static void ClearFWHole(struct alias_link
*link
);
464 /* Log file control */
465 static void InitPacketAliasLog(void);
466 static void UninitPacketAliasLog(void);
469 StartPointIn(struct in_addr alias_addr
,
475 n
= alias_addr
.s_addr
;
476 if (link_type
!= LINK_PPTP
)
479 return(n
% LINK_TABLE_IN_SIZE
);
484 StartPointOut(struct in_addr src_addr
, struct in_addr dst_addr
,
485 u_short src_port
, u_short dst_port
, int link_type
)
490 n
+= dst_addr
.s_addr
;
491 if (link_type
!= LINK_PPTP
) {
497 return(n
% LINK_TABLE_OUT_SIZE
);
502 SeqDiff(__uint32_t x
, __uint32_t y
)
504 /* Return the difference between two TCP sequence numbers */
507 This function is encapsulated in case there are any unusual
508 arithmetic conditions that need to be considered.
511 return (ntohl(y
) - ntohl(x
));
519 /* Used for debugging */
523 fprintf(monitorFile
, "icmp=%d, udp=%d, tcp=%d, pptp=%d, proto=%d, frag_id=%d frag_ptr=%d",
530 fragmentPtrLinkCount
);
532 fprintf(monitorFile
, " / tot=%d (sock=%d)\n",
533 icmpLinkCount
+ udpLinkCount
537 + fragmentIdLinkCount
538 + fragmentPtrLinkCount
,
550 /* Internal routines for finding, deleting and adding links
553 GetNewPort() -- find and reserve new alias port number
554 GetSocket() -- try to allocate a socket for a given port
556 Link creation and deletion:
557 CleanupAliasData() - remove all link chains from lookup table
558 IncrementalCleanup() - look for stale links in a single chain
559 DeleteLink() - remove link
561 ReLink() - change link
564 FindLinkOut() - find link for outgoing packets
565 FindLinkIn() - find link for incoming packets
568 FindNewPortGroup() - find an available group of ports
571 /* Local prototypes */
572 static int GetNewPort(struct alias_link
*, int);
574 static u_short
GetSocket(u_short
, int *, int);
576 static void CleanupAliasData(void);
578 static void IncrementalCleanup(void);
580 static void DeleteLink(struct alias_link
*);
582 static struct alias_link
*
583 AddLink(struct in_addr
, struct in_addr
, struct in_addr
,
584 u_short
, u_short
, int, int);
586 static struct alias_link
*
587 ReLink(struct alias_link
*,
588 struct in_addr
, struct in_addr
, struct in_addr
,
589 u_short
, u_short
, int, int);
591 static struct alias_link
*
592 FindLinkOut(struct in_addr
, struct in_addr
, u_short
, u_short
, int, int);
594 static struct alias_link
*
595 FindLinkIn(struct in_addr
, struct in_addr
, u_short
, u_short
, int, int);
598 #define ALIAS_PORT_BASE 0x08000
599 #define ALIAS_PORT_MASK 0x07fff
600 #define ALIAS_PORT_MASK_EVEN 0x07ffe
601 #define GET_NEW_PORT_MAX_ATTEMPTS 20
603 #define GET_ALIAS_PORT -1
604 #define GET_ALIAS_EPHEMERAL_PORT -2
605 #define GET_ALIAS_ID GET_ALIAS_PORT
607 #define FIND_EVEN_ALIAS_BASE 1
609 /* GetNewPort() allocates port numbers. Note that if a port number
610 is already in use, that does not mean that it cannot be used by
611 another link concurrently. This is because GetNewPort() looks for
612 unused triplets: (dest addr, dest port, alias port). */
615 GetEphemeralPort(struct alias_link
*link
)
619 /* Port number search */
620 for (i
=0; i
< GET_NEW_PORT_MAX_ATTEMPTS
; i
++)
622 struct sockaddr_in sock_addr
;
625 struct alias_link
*search_result
;
627 if (GetSocket(0, &link
->sockfd
, link
->link_type
) == 0)
629 salen
= sizeof(struct sockaddr_in
);
630 if (getsockname(link
->sockfd
, (struct sockaddr
*)&sock_addr
, &salen
) == -1)
632 port_net
= sock_addr
.sin_port
;
634 search_result
= FindLinkIn(link
->dst_addr
, link
->alias_addr
,
635 link
->dst_port
, port_net
,
638 if (search_result
== NULL
) {
639 link
->alias_port
= port_net
;
646 fprintf(stderr
, "PacketAlias/GetEphemeralPort(): ");
647 fprintf(stderr
, "could not find free port\n");
654 GetNewPort(struct alias_link
*link
, int alias_port_param
)
661 if (alias_port_param
== GET_ALIAS_EPHEMERAL_PORT
)
662 return GetEphemeralPort(link
);
665 Description of alias_port_param for GetNewPort(). When
666 this parameter is zero or positive, it precisely specifies
667 the port number. GetNewPort() will return this number
668 without check that it is in use.
670 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
671 selected port number.
673 if (alias_port_param
== GET_ALIAS_PORT
)
676 * The aliasing port is automatically selected
677 * by one of two methods below:
679 max_trials
= GET_NEW_PORT_MAX_ATTEMPTS
;
681 if (packetAliasMode
& PKT_ALIAS_SAME_PORTS
)
684 * When the PKT_ALIAS_SAME_PORTS option is
685 * chosen, the first try will be the
686 * actual source port. If this is already
687 * in use, the remainder of the trials
690 port_net
= link
->src_port
;
691 port_sys
= ntohs(port_net
);
695 /* First trial and all subsequent are random. */
696 port_sys
= random() & ALIAS_PORT_MASK
;
697 port_sys
+= ALIAS_PORT_BASE
;
698 port_net
= htons(port_sys
);
701 else if (alias_port_param
>= 0 && alias_port_param
< 0x10000)
703 link
->alias_port
= (u_short
) alias_port_param
;
709 fprintf(stderr
, "PacketAlias/GetNewPort(): ");
710 fprintf(stderr
, "input parameter error\n");
716 /* Port number search */
717 for (i
=0; i
<max_trials
; i
++)
720 struct alias_link
*search_result
;
722 search_result
= FindLinkIn(link
->dst_addr
, link
->alias_addr
,
723 link
->dst_port
, port_net
,
726 if (search_result
== NULL
)
728 else if (!(link
->flags
& LINK_PARTIALLY_SPECIFIED
)
729 && (search_result
->flags
& LINK_PARTIALLY_SPECIFIED
))
736 if ((packetAliasMode
& PKT_ALIAS_USE_SOCKETS
)
737 && (link
->flags
& LINK_PARTIALLY_SPECIFIED
)
738 && ((link
->link_type
== LINK_TCP
) ||
739 (link
->link_type
== LINK_UDP
)))
741 if (GetSocket(port_net
, &link
->sockfd
, link
->link_type
))
743 link
->alias_port
= port_net
;
749 link
->alias_port
= port_net
;
754 port_sys
= random() & ALIAS_PORT_MASK
;
755 port_sys
+= ALIAS_PORT_BASE
;
756 port_net
= htons(port_sys
);
759 fprintf(stderr
, "PacketAlias/GetnewPort(): ");
760 fprintf(stderr
, "could not find free port\n");
768 GetSocket(u_short port_net
, int *sockfd
, int link_type
)
772 struct sockaddr_in sock_addr
;
774 if (link_type
== LINK_TCP
)
775 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
776 else if (link_type
== LINK_UDP
)
777 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
781 fprintf(stderr
, "PacketAlias/GetSocket(): ");
782 fprintf(stderr
, "incorrect link type\n");
790 fprintf(stderr
, "PacketAlias/GetSocket(): ");
791 fprintf(stderr
, "socket() error %d\n", *sockfd
);
796 sock_addr
.sin_family
= AF_INET
;
797 sock_addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
798 sock_addr
.sin_port
= port_net
;
801 (struct sockaddr
*) &sock_addr
,
817 /* FindNewPortGroup() returns a base port number for an available
818 range of contiguous port numbers. Note that if a port number
819 is already in use, that does not mean that it cannot be used by
820 another link concurrently. This is because FindNewPortGroup()
821 looks for unused triplets: (dest addr, dest port, alias port). */
824 FindNewPortGroup(struct in_addr dst_addr
,
825 struct in_addr alias_addr
,
838 * Get link_type from protocol
844 link_type
= LINK_UDP
;
847 link_type
= LINK_TCP
;
855 * The aliasing port is automatically selected
856 * by one of two methods below:
858 max_trials
= GET_NEW_PORT_MAX_ATTEMPTS
;
860 if (packetAliasMode
& PKT_ALIAS_SAME_PORTS
) {
862 * When the ALIAS_SAME_PORTS option is
863 * chosen, the first try will be the
864 * actual source port. If this is already
865 * in use, the remainder of the trials
868 port_sys
= ntohs(src_port
);
872 /* First trial and all subsequent are random. */
873 if (align
== FIND_EVEN_ALIAS_BASE
)
874 port_sys
= random() & ALIAS_PORT_MASK_EVEN
;
876 port_sys
= random() & ALIAS_PORT_MASK
;
878 port_sys
+= ALIAS_PORT_BASE
;
881 /* Port number search */
882 for (i
= 0; i
< max_trials
; i
++) {
884 struct alias_link
*search_result
;
886 for (j
= 0; j
< port_count
; j
++)
887 if (0 != (search_result
= FindLinkIn(dst_addr
, alias_addr
,
888 dst_port
, htons(port_sys
+ j
),
892 /* Found a good range, return base */
894 return (htons(port_sys
));
896 /* Find a new base to try */
897 if (align
== FIND_EVEN_ALIAS_BASE
)
898 port_sys
= random() & ALIAS_PORT_MASK_EVEN
;
900 port_sys
= random() & ALIAS_PORT_MASK
;
902 port_sys
+= ALIAS_PORT_BASE
;
906 fprintf(stderr
, "PacketAlias/FindNewPortGroup(): ");
907 fprintf(stderr
, "could not find free port(s)\n");
914 CleanupAliasData(void)
916 struct alias_link
*link
;
920 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
922 link
= LIST_FIRST(&linkTableOut
[i
]);
925 struct alias_link
*link_next
;
926 link_next
= LIST_NEXT(link
, list_out
);
938 IncrementalCleanup(void)
941 struct alias_link
*link
;
944 link
= LIST_FIRST(&linkTableOut
[cleanupIndex
++]);
948 struct alias_link
*link_next
;
950 link_next
= LIST_NEXT(link
, list_out
);
951 idelta
= timeStamp
- link
->timestamp
;
952 switch (link
->link_type
)
955 if (idelta
> link
->expire_time
)
957 struct tcp_dat
*tcp_aux
;
959 tcp_aux
= link
->data
.tcp
;
960 if (tcp_aux
->state
.in
!= ALIAS_TCP_STATE_CONNECTED
961 || tcp_aux
->state
.out
!= ALIAS_TCP_STATE_CONNECTED
)
969 if (idelta
> link
->expire_time
)
979 if (cleanupIndex
== LINK_TABLE_OUT_SIZE
)
984 DeleteLink(struct alias_link
*link
)
987 /* Don't do anything if the link is marked permanent */
988 if (deleteAllLinks
== 0 && link
->flags
& LINK_PERMANENT
)
992 /* Delete associated firewall hole, if any */
996 /* Free memory allocated for LSNAT server pool */
997 if (link
->server
!= NULL
) {
998 struct server
*head
, *curr
, *next
;
1000 head
= curr
= link
->server
;
1004 } while ((curr
= next
) != head
);
1007 /* Adjust output table pointers */
1008 LIST_REMOVE(link
, list_out
);
1010 /* Adjust input table pointers */
1011 LIST_REMOVE(link
, list_in
);
1013 /* Close socket, if one has been allocated */
1014 if (link
->sockfd
!= -1)
1017 close(link
->sockfd
);
1020 /* Link-type dependent cleanup */
1021 switch(link
->link_type
)
1031 free(link
->data
.tcp
);
1036 case LINK_FRAGMENT_ID
:
1037 fragmentIdLinkCount
--;
1039 case LINK_FRAGMENT_PTR
:
1040 fragmentPtrLinkCount
--;
1041 if (link
->data
.frag_ptr
!= NULL
)
1042 free(link
->data
.frag_ptr
);
1052 if ((packetAliasMode
& PKT_ALIAS_LOG
) != 0 &&
1053 !IN_MULTICAST(link
->src_addr
.s_addr
) &&
1054 !IN_MULTICAST(link
->dst_addr
.s_addr
))
1060 switch(link
->link_type
)
1071 fprintf(monitorFile
, "Deleted%s %s:%d<->%s:%d to %s:%d<->%s:%d\n",
1073 inet_ntop(AF_INET
, &link
->src_addr
, src
, sizeof(src
)), link
->src_port
,
1074 inet_ntop(AF_INET
, &link
->dst_addr
, dst
, sizeof(dst
)), link
->dst_port
,
1075 inet_ntop(AF_INET
, &link
->alias_addr
, alias
, sizeof(alias
)), link
->alias_port
,
1076 dst
, link
->dst_port
);
1077 fflush(monitorFile
);
1080 if (packetAliasMode
& PKT_ALIAS_LOG
)
1089 static struct alias_link
*
1090 AddLink(struct in_addr src_addr
,
1091 struct in_addr dst_addr
,
1092 struct in_addr alias_addr
,
1095 int alias_port_param
, /* if less than zero, alias */
1096 int link_type
) /* port will be automatically */
1097 { /* chosen. If greater than */
1098 u_int start_point
; /* zero, equal to alias port */
1099 struct alias_link
*link
;
1101 link
= malloc(sizeof(struct alias_link
));
1104 /* Basic initialization */
1105 link
->src_addr
= src_addr
;
1106 link
->dst_addr
= dst_addr
;
1107 link
->alias_addr
= alias_addr
;
1108 link
->proxy_addr
.s_addr
= INADDR_ANY
;
1109 link
->src_port
= src_port
;
1110 link
->dst_port
= dst_port
;
1111 link
->proxy_port
= 0;
1112 link
->server
= NULL
;
1113 link
->link_type
= link_type
;
1116 link
->timestamp
= timeStamp
;
1118 /* Expiration time */
1122 link
->expire_time
= ICMP_EXPIRE_TIME
;
1125 if (dst_addr
.s_addr
== 0 && dst_port
== 0)
1126 link
->expire_time
= UDP_EXPIRE_TIME
* 5;
1128 link
->expire_time
= UDP_EXPIRE_TIME
;
1131 link
->expire_time
= TCP_EXPIRE_INITIAL
;
1134 link
->flags
|= LINK_PERMANENT
; /* no timeout. */
1136 case LINK_FRAGMENT_ID
:
1137 link
->expire_time
= FRAGMENT_ID_EXPIRE_TIME
;
1139 case LINK_FRAGMENT_PTR
:
1140 link
->expire_time
= FRAGMENT_PTR_EXPIRE_TIME
;
1145 link
->expire_time
= PROTO_EXPIRE_TIME
;
1149 /* Determine alias flags */
1150 if (dst_addr
.s_addr
== INADDR_ANY
)
1151 link
->flags
|= LINK_UNKNOWN_DEST_ADDR
;
1153 link
->flags
|= LINK_UNKNOWN_DEST_PORT
;
1155 /* Determine alias port */
1156 if (GetNewPort(link
, alias_port_param
) != 0)
1161 /* Link-type dependent initialization */
1164 struct tcp_dat
*aux_tcp
;
1173 aux_tcp
= malloc(sizeof(struct tcp_dat
));
1174 if (aux_tcp
!= NULL
)
1179 aux_tcp
->state
.in
= ALIAS_TCP_STATE_NOT_CONNECTED
;
1180 aux_tcp
->state
.out
= ALIAS_TCP_STATE_NOT_CONNECTED
;
1181 aux_tcp
->state
.index
= 0;
1182 aux_tcp
->state
.ack_modified
= 0;
1183 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
1184 aux_tcp
->ack
[i
].active
= 0;
1185 aux_tcp
->fwhole
= -1;
1186 link
->data
.tcp
= aux_tcp
;
1191 fprintf(stderr
, "PacketAlias/AddLink: ");
1192 fprintf(stderr
, " cannot allocate auxiliary TCP data\n");
1201 case LINK_FRAGMENT_ID
:
1202 fragmentIdLinkCount
++;
1204 case LINK_FRAGMENT_PTR
:
1205 fragmentPtrLinkCount
++;
1214 /* Set up pointers for output lookup table */
1215 start_point
= StartPointOut(src_addr
, dst_addr
,
1216 src_port
, dst_port
, link_type
);
1217 LIST_INSERT_HEAD(&linkTableOut
[start_point
], link
, list_out
);
1219 /* Set up pointers for input lookup table */
1220 start_point
= StartPointIn(alias_addr
, link
->alias_port
, link_type
);
1221 LIST_INSERT_HEAD(&linkTableIn
[start_point
], link
, list_in
);
1226 fprintf(stderr
, "PacketAlias/AddLink(): ");
1227 fprintf(stderr
, "malloc() call failed.\n");
1232 if ((packetAliasMode
& PKT_ALIAS_LOG
) != 0 &&
1233 !IN_MULTICAST(link
->src_addr
.s_addr
) &&
1234 !IN_MULTICAST(link
->dst_addr
.s_addr
))
1240 switch(link
->link_type
)
1251 fprintf(monitorFile
, "Added %s %s:%d<->%s:%d to %s:%d<->%s:%d\n",
1253 inet_ntop(AF_INET
, &link
->src_addr
, src
, sizeof(src
)), link
->src_port
,
1254 inet_ntop(AF_INET
, &link
->dst_addr
, dst
, sizeof(dst
)), link
->dst_port
,
1255 inet_ntop(AF_INET
, &link
->alias_addr
, alias
, sizeof(alias
)), link
->alias_port
,
1256 dst
, link
->dst_port
);
1259 if (packetAliasMode
& PKT_ALIAS_LOG
)
1266 static struct alias_link
*
1267 ReLink(struct alias_link
*old_link
,
1268 struct in_addr src_addr
,
1269 struct in_addr dst_addr
,
1270 struct in_addr alias_addr
,
1273 int alias_port_param
, /* if less than zero, alias */
1274 int link_type
) /* port will be automatically */
1275 { /* chosen. If greater than */
1276 struct alias_link
*new_link
; /* zero, equal to alias port */
1278 new_link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1279 src_port
, dst_port
, alias_port_param
,
1282 if (new_link
!= NULL
&&
1283 old_link
->link_type
== LINK_TCP
&&
1284 old_link
->data
.tcp
->fwhole
> 0) {
1285 PunchFWHole(new_link
);
1288 if ((old_link
->flags
& LINK_CONE
) == 0)
1289 DeleteLink(old_link
);
1293 static struct alias_link
*
1294 _FindLinkOut(struct in_addr src_addr
,
1295 struct in_addr dst_addr
,
1299 int replace_partial_links
)
1302 struct alias_link
*link
;
1304 i
= StartPointOut(src_addr
, dst_addr
, src_port
, dst_port
, link_type
);
1305 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1307 if (link
->src_addr
.s_addr
== src_addr
.s_addr
1308 && link
->server
== NULL
1309 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
1310 && link
->dst_port
== dst_port
1311 && link
->src_port
== src_port
1312 && link
->link_type
== link_type
)
1314 link
->timestamp
= timeStamp
;
1319 /* Search for partially specified links. */
1320 if (link
== NULL
&& replace_partial_links
)
1322 if (dst_port
!= 0 && dst_addr
.s_addr
!= INADDR_ANY
)
1324 link
= _FindLinkOut(src_addr
, dst_addr
, src_port
, 0,
1327 link
= _FindLinkOut(src_addr
, nullAddress
, src_port
,
1328 dst_port
, link_type
, 0);
1331 (dst_port
!= 0 || dst_addr
.s_addr
!= INADDR_ANY
))
1333 link
= _FindLinkOut(src_addr
, nullAddress
, src_port
, 0,
1339 src_addr
, dst_addr
, link
->alias_addr
,
1340 src_port
, dst_port
, link
->alias_port
,
1348 static struct alias_link
*
1349 FindLinkOut(struct in_addr src_addr
,
1350 struct in_addr dst_addr
,
1354 int replace_partial_links
)
1356 struct alias_link
*link
;
1358 link
= _FindLinkOut(src_addr
, dst_addr
, src_port
, dst_port
,
1359 link_type
, replace_partial_links
);
1363 /* The following allows permanent links to be
1364 specified as using the default source address
1365 (i.e. device interface address) without knowing
1366 in advance what that address is. */
1367 if (aliasAddress
.s_addr
!= 0 &&
1368 src_addr
.s_addr
== aliasAddress
.s_addr
)
1370 link
= _FindLinkOut(nullAddress
, dst_addr
, src_port
, dst_port
,
1371 link_type
, replace_partial_links
);
1379 static struct alias_link
*
1380 _FindLinkIn(struct in_addr dst_addr
,
1381 struct in_addr alias_addr
,
1385 int replace_partial_links
)
1389 struct alias_link
*link
;
1390 struct alias_link
*link_fully_specified
;
1391 struct alias_link
*link_unknown_all
;
1392 struct alias_link
*link_unknown_dst_addr
;
1393 struct alias_link
*link_unknown_dst_port
;
1395 /* Initialize pointers */
1396 link_fully_specified
= NULL
;
1397 link_unknown_all
= NULL
;
1398 link_unknown_dst_addr
= NULL
;
1399 link_unknown_dst_port
= NULL
;
1401 /* If either the dest addr or port is unknown, the search
1402 loop will have to know about this. */
1405 if (dst_addr
.s_addr
== INADDR_ANY
)
1406 flags_in
|= LINK_UNKNOWN_DEST_ADDR
;
1408 flags_in
|= LINK_UNKNOWN_DEST_PORT
;
1411 start_point
= StartPointIn(alias_addr
, alias_port
, link_type
);
1412 LIST_FOREACH(link
, &linkTableIn
[start_point
], list_in
)
1416 flags
= flags_in
| link
->flags
;
1417 if (!(flags
& LINK_PARTIALLY_SPECIFIED
))
1419 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1420 && link
->alias_port
== alias_port
1421 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
1422 && link
->dst_port
== dst_port
1423 && link
->link_type
== link_type
)
1425 link_fully_specified
= link
;
1429 else if ((flags
& LINK_UNKNOWN_DEST_ADDR
)
1430 && (flags
& LINK_UNKNOWN_DEST_PORT
))
1432 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1433 && link
->alias_port
== alias_port
1434 && link
->link_type
== link_type
)
1436 if (link_unknown_all
== NULL
)
1437 link_unknown_all
= link
;
1440 else if (flags
& LINK_UNKNOWN_DEST_ADDR
)
1442 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1443 && link
->alias_port
== alias_port
1444 && link
->link_type
== link_type
1445 && link
->dst_port
== dst_port
)
1447 if (link_unknown_dst_addr
== NULL
)
1448 link_unknown_dst_addr
= link
;
1451 else if (flags
& LINK_UNKNOWN_DEST_PORT
)
1453 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1454 && link
->alias_port
== alias_port
1455 && link
->link_type
== link_type
1456 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
)
1458 if (link_unknown_dst_port
== NULL
)
1459 link_unknown_dst_port
= link
;
1466 if (link_fully_specified
!= NULL
)
1468 link_fully_specified
->timestamp
= timeStamp
;
1469 link
= link_fully_specified
;
1471 else if (link_unknown_dst_port
!= NULL
)
1472 link
= link_unknown_dst_port
;
1473 else if (link_unknown_dst_addr
!= NULL
)
1474 link
= link_unknown_dst_addr
;
1475 else if (link_unknown_all
!= NULL
)
1476 link
= link_unknown_all
;
1480 if (replace_partial_links
&&
1481 (link
->flags
& LINK_PARTIALLY_SPECIFIED
|| link
->server
!= NULL
))
1483 struct in_addr src_addr
;
1486 if (link
->server
!= NULL
) { /* LSNAT link */
1487 src_addr
= link
->server
->addr
;
1488 src_port
= link
->server
->port
;
1489 link
->server
= link
->server
->next
;
1491 src_addr
= link
->src_addr
;
1492 src_port
= link
->src_port
;
1496 src_addr
, dst_addr
, alias_addr
,
1497 src_port
, dst_port
, alias_port
,
1504 static struct alias_link
*
1505 FindLinkIn(struct in_addr dst_addr
,
1506 struct in_addr alias_addr
,
1510 int replace_partial_links
)
1512 struct alias_link
*link
;
1514 link
= _FindLinkIn(dst_addr
, alias_addr
, dst_port
, alias_port
,
1515 link_type
, replace_partial_links
);
1519 /* The following allows permanent links to be
1520 specified as using the default aliasing address
1521 (i.e. device interface address) without knowing
1522 in advance what that address is. */
1523 if (aliasAddress
.s_addr
!= 0 &&
1524 alias_addr
.s_addr
== aliasAddress
.s_addr
)
1526 link
= _FindLinkIn(dst_addr
, nullAddress
, dst_port
, alias_port
,
1527 link_type
, replace_partial_links
);
1537 /* External routines for finding/adding links
1539 -- "external" means outside alias_db.c, but within alias*.c --
1541 FindIcmpIn(), FindIcmpOut()
1542 FindFragmentIn1(), FindFragmentIn2()
1543 AddFragmentPtrLink(), FindFragmentPtr()
1544 FindProtoIn(), FindProtoOut()
1545 FindUdpTcpIn(), FindUdpTcpOut()
1546 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1547 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1548 FindOriginalAddress(), FindAliasAddress()
1550 (prototypes in alias_local.h)
1555 FindIcmpIn(struct in_addr dst_addr
,
1556 struct in_addr alias_addr
,
1560 struct alias_link
*link
;
1562 link
= FindLinkIn(dst_addr
, alias_addr
,
1563 NO_DEST_PORT
, id_alias
,
1565 if (link
== NULL
&& create
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1567 struct in_addr target_addr
;
1569 target_addr
= FindOriginalAddress(alias_addr
);
1570 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1571 id_alias
, NO_DEST_PORT
, id_alias
,
1580 FindIcmpOut(struct in_addr src_addr
,
1581 struct in_addr dst_addr
,
1585 struct alias_link
* link
;
1587 link
= FindLinkOut(src_addr
, dst_addr
,
1590 if (link
== NULL
&& create
)
1592 struct in_addr alias_addr
;
1594 alias_addr
= FindAliasAddress(src_addr
);
1595 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1596 id
, NO_DEST_PORT
, GET_ALIAS_ID
,
1605 FindFragmentIn1(struct in_addr dst_addr
,
1606 struct in_addr alias_addr
,
1609 struct alias_link
*link
;
1611 link
= FindLinkIn(dst_addr
, alias_addr
,
1612 NO_DEST_PORT
, ip_id
,
1613 LINK_FRAGMENT_ID
, 0);
1617 link
= AddLink(nullAddress
, dst_addr
, alias_addr
,
1618 NO_SRC_PORT
, NO_DEST_PORT
, ip_id
,
1627 FindFragmentIn2(struct in_addr dst_addr
, /* Doesn't add a link if one */
1628 struct in_addr alias_addr
, /* is not found. */
1631 return FindLinkIn(dst_addr
, alias_addr
,
1632 NO_DEST_PORT
, ip_id
,
1633 LINK_FRAGMENT_ID
, 0);
1638 AddFragmentPtrLink(struct in_addr dst_addr
,
1641 return AddLink(nullAddress
, dst_addr
, nullAddress
,
1642 NO_SRC_PORT
, NO_DEST_PORT
, ip_id
,
1648 FindFragmentPtr(struct in_addr dst_addr
,
1651 return FindLinkIn(dst_addr
, nullAddress
,
1652 NO_DEST_PORT
, ip_id
,
1653 LINK_FRAGMENT_PTR
, 0);
1658 FindProtoIn(struct in_addr dst_addr
,
1659 struct in_addr alias_addr
,
1662 struct alias_link
*link
;
1664 link
= FindLinkIn(dst_addr
, alias_addr
,
1668 if (link
== NULL
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1670 struct in_addr target_addr
;
1672 target_addr
= FindOriginalAddress(alias_addr
);
1673 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1674 NO_SRC_PORT
, NO_DEST_PORT
, 0,
1683 FindProtoOut(struct in_addr src_addr
,
1684 struct in_addr dst_addr
,
1687 struct alias_link
*link
;
1689 link
= FindLinkOut(src_addr
, dst_addr
,
1690 NO_SRC_PORT
, NO_DEST_PORT
,
1695 struct in_addr alias_addr
;
1697 alias_addr
= FindAliasAddress(src_addr
);
1698 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1699 NO_SRC_PORT
, NO_DEST_PORT
, 0,
1708 FindUdpTcpIn(struct in_addr dst_addr
,
1709 struct in_addr alias_addr
,
1716 struct alias_link
*link
;
1721 link_type
= LINK_UDP
;
1724 link_type
= LINK_TCP
;
1731 link
= FindLinkIn(dst_addr
, alias_addr
,
1732 dst_port
, alias_port
,
1735 if (link
== NULL
&& create
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1737 struct in_addr target_addr
;
1739 target_addr
= FindOriginalAddress(alias_addr
);
1740 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1741 alias_port
, dst_port
, alias_port
,
1750 FindUdpTcpOut(struct in_addr src_addr
,
1751 struct in_addr dst_addr
,
1758 struct alias_link
*link
;
1763 link_type
= LINK_UDP
;
1766 link_type
= LINK_TCP
;
1773 link
= FindLinkOut(src_addr
, dst_addr
, src_port
, dst_port
, link_type
, create
);
1775 if (link
== NULL
&& create
)
1777 struct in_addr alias_addr
;
1778 struct in_addr dst_addr2
= dst_addr
;
1779 u_short dst_port2
= dst_port
;
1781 alias_addr
= FindAliasAddress(src_addr
);
1783 if (iChatAVHack
&& link_type
== LINK_UDP
&& dst_port
== htons(5678)) {
1784 dst_addr2
.s_addr
= 0;
1787 link
= AddLink(src_addr
, dst_addr2
, alias_addr
,
1788 src_port
, dst_port2
, GET_ALIAS_PORT
,
1791 (link
->flags
& (LINK_UNKNOWN_DEST_ADDR
| LINK_UNKNOWN_DEST_PORT
)) != 0)
1793 link
->flags
|= LINK_CONE
;
1794 link
= ReLink(link
, link
->src_addr
, dst_addr
, link
->alias_addr
,
1795 link
->src_port
, dst_port
, link
->alias_port
, link_type
);
1804 AddPptp(struct in_addr src_addr
,
1805 struct in_addr dst_addr
,
1806 struct in_addr alias_addr
,
1807 u_int16_t src_call_id
)
1809 struct alias_link
*link
;
1811 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1812 src_call_id
, 0, GET_ALIAS_PORT
,
1820 FindPptpOutByCallId(struct in_addr src_addr
,
1821 struct in_addr dst_addr
,
1822 u_int16_t src_call_id
)
1825 struct alias_link
*link
;
1827 i
= StartPointOut(src_addr
, dst_addr
, 0, 0, LINK_PPTP
);
1828 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1829 if (link
->link_type
== LINK_PPTP
&&
1830 link
->src_addr
.s_addr
== src_addr
.s_addr
&&
1831 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1832 link
->src_port
== src_call_id
)
1840 FindPptpOutByPeerCallId(struct in_addr src_addr
,
1841 struct in_addr dst_addr
,
1842 u_int16_t dst_call_id
)
1845 struct alias_link
*link
;
1847 i
= StartPointOut(src_addr
, dst_addr
, 0, 0, LINK_PPTP
);
1848 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1849 if (link
->link_type
== LINK_PPTP
&&
1850 link
->src_addr
.s_addr
== src_addr
.s_addr
&&
1851 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1852 link
->dst_port
== dst_call_id
)
1860 FindPptpInByCallId(struct in_addr dst_addr
,
1861 struct in_addr alias_addr
,
1862 u_int16_t dst_call_id
)
1865 struct alias_link
*link
;
1867 i
= StartPointIn(alias_addr
, 0, LINK_PPTP
);
1868 LIST_FOREACH(link
, &linkTableIn
[i
], list_in
)
1869 if (link
->link_type
== LINK_PPTP
&&
1870 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1871 link
->alias_addr
.s_addr
== alias_addr
.s_addr
&&
1872 link
->dst_port
== dst_call_id
)
1880 FindPptpInByPeerCallId(struct in_addr dst_addr
,
1881 struct in_addr alias_addr
,
1882 u_int16_t alias_call_id
)
1884 struct alias_link
*link
;
1886 link
= FindLinkIn(dst_addr
, alias_addr
,
1887 0/* any */, alias_call_id
,
1896 FindRtspOut(struct in_addr src_addr
,
1897 struct in_addr dst_addr
,
1903 struct alias_link
*link
;
1908 link_type
= LINK_UDP
;
1911 link_type
= LINK_TCP
;
1918 link
= FindLinkOut(src_addr
, dst_addr
, src_port
, 0, link_type
, 1);
1922 struct in_addr alias_addr
;
1924 alias_addr
= FindAliasAddress(src_addr
);
1925 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1926 src_port
, 0, alias_port
,
1935 FindOriginalAddress(struct in_addr alias_addr
)
1937 struct alias_link
*link
;
1939 link
= FindLinkIn(nullAddress
, alias_addr
,
1940 0, 0, LINK_ADDR
, 0);
1944 if (targetAddress
.s_addr
== INADDR_ANY
)
1946 else if (targetAddress
.s_addr
== INADDR_NONE
)
1947 return aliasAddress
;
1949 return targetAddress
;
1953 if (link
->server
!= NULL
) { /* LSNAT link */
1954 struct in_addr src_addr
;
1956 src_addr
= link
->server
->addr
;
1957 link
->server
= link
->server
->next
;
1959 } else if (link
->src_addr
.s_addr
== INADDR_ANY
)
1960 return aliasAddress
;
1962 return link
->src_addr
;
1968 FindAliasAddress(struct in_addr original_addr
)
1970 struct alias_link
*link
;
1972 link
= FindLinkOut(original_addr
, nullAddress
,
1973 0, 0, LINK_ADDR
, 0);
1976 return aliasAddress
;
1980 if (link
->alias_addr
.s_addr
== INADDR_ANY
)
1981 return aliasAddress
;
1983 return link
->alias_addr
;
1987 /* FindAliasPortOut */
1988 /* external routine for NatPortMap */
1989 /* return alias port for the src_addr,dst_addr,src_port and proto */
1990 /* if one doesn't existed, create a mapping with providing pub_port if it's not 0 */
1991 /* delete mapping if addmapping is not true */
1993 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
)
1996 struct alias_link
*link
;
2002 link_type
= LINK_UDP
;
2005 link_type
= LINK_TCP
;
2016 printf("FindAliasPortOut:: srcaddr= %s:%u, ",
2017 inet_ntoa(src_addr
), ntohs(src_port
));
2018 printf("dstadd= %s:%u link_type= %d, lifetime= %d\n",
2019 inet_ntoa(dst_addr
), ntohs(pub_port
), link_type
, lifetime
);
2021 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
2023 link
= LIST_FIRST(&linkTableOut
[i
]);
2024 while (link
!= NULL
)
2026 struct alias_link
*link_next
;
2027 char src_str
[32], dst_str
[32], alias_str
[32];
2029 snprintf(src_str
, sizeof(src_str
), "%s:%u",
2030 inet_ntoa(link
->src_addr
), ntohs(link
->src_port
));
2031 snprintf(dst_str
, sizeof(dst_str
), "%s:%u",
2032 inet_ntoa(link
->dst_addr
), ntohs(link
->dst_port
));
2033 snprintf(alias_str
, sizeof(alias_str
), "%s:%u",
2034 inet_ntoa(link
->alias_addr
), ntohs(link
->alias_port
));
2036 printf(" linkTableOut[%d:%d] src= %s dst= %s alias= %s flags= 0x%x linktype= %d ts= %d exp= %d fd= %d\n",
2037 i
, icount
, src_str
, dst_str
, alias_str
,
2038 link
->flags
, link
->link_type
, link
->timestamp
, link
->expire_time
, link
->sockfd
);
2040 link_next
= LIST_NEXT(link
, list_out
);
2049 i
= StartPointOut(src_addr
, dst_addr
, src_port
, 0, link_type
);
2051 printf("PORTMAP::StartPointOut returns %d\n", i
);
2053 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
2055 if (link
->src_addr
.s_addr
== src_addr
.s_addr
&&
2056 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
2057 link
->src_port
== src_port
&& link
->link_type
== link_type
)
2061 if ( link
== NULL
&& addmapping
)
2063 struct in_addr alias_addr
;
2065 printf("PORTMAP:: cannot find mapping, adding mapping private port =%d, public port = %d\n",
2066 src_port
, pub_port
);
2068 /* address/port in not in list, create new mapping */
2070 alias_addr
= FindAliasAddress(src_addr
);
2071 /* create new mapping */
2072 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2073 src_port
, 0, GET_ALIAS_EPHEMERAL_PORT
,
2075 if ( link
!= NULL
) {
2076 /* link was create, set new lifetime */
2077 SetExpire(link
, lifetime
);
2078 /* Prevent link deletion when incoming connection arrive */
2079 link
->flags
|= LINK_CONE
;
2085 return( GetAliasPort(link
));
2088 SetExpire(link
, 0); /* delete mapping */
2097 /* External routines for getting or changing link data
2098 (external to alias_db.c, but internal to alias*.c)
2100 SetFragmentData(), GetFragmentData()
2101 SetFragmentPtr(), GetFragmentPtr()
2102 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
2103 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
2104 GetOriginalPort(), GetAliasPort()
2105 SetAckModified(), GetAckModified()
2106 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
2107 SetLastLineCrlfTermed(), GetLastLineCrlfTermed()
2113 SetFragmentAddr(struct alias_link
*link
, struct in_addr src_addr
)
2115 link
->data
.frag_addr
= src_addr
;
2120 GetFragmentAddr(struct alias_link
*link
, struct in_addr
*src_addr
)
2122 *src_addr
= link
->data
.frag_addr
;
2127 SetFragmentPtr(struct alias_link
*link
, char *fptr
)
2129 link
->data
.frag_ptr
= fptr
;
2134 GetFragmentPtr(struct alias_link
*link
, char **fptr
)
2136 *fptr
= link
->data
.frag_ptr
;
2141 SetStateIn(struct alias_link
*link
, int state
)
2143 /* TCP input state */
2145 case ALIAS_TCP_STATE_DISCONNECTED
:
2146 if (link
->data
.tcp
->state
.out
!= ALIAS_TCP_STATE_CONNECTED
)
2147 link
->expire_time
= TCP_EXPIRE_DEAD
;
2149 link
->expire_time
= TCP_EXPIRE_SINGLEDEAD
;
2151 case ALIAS_TCP_STATE_CONNECTED
:
2152 if (link
->data
.tcp
->state
.out
== ALIAS_TCP_STATE_CONNECTED
)
2153 link
->expire_time
= TCP_EXPIRE_CONNECTED
;
2158 link
->data
.tcp
->state
.in
= state
;
2163 SetStateOut(struct alias_link
*link
, int state
)
2165 /* TCP output state */
2167 case ALIAS_TCP_STATE_DISCONNECTED
:
2168 if (link
->data
.tcp
->state
.in
!= ALIAS_TCP_STATE_CONNECTED
)
2169 link
->expire_time
= TCP_EXPIRE_DEAD
;
2171 link
->expire_time
= TCP_EXPIRE_SINGLEDEAD
;
2173 case ALIAS_TCP_STATE_CONNECTED
:
2174 if (link
->data
.tcp
->state
.in
== ALIAS_TCP_STATE_CONNECTED
)
2175 link
->expire_time
= TCP_EXPIRE_CONNECTED
;
2180 link
->data
.tcp
->state
.out
= state
;
2185 GetStateIn(struct alias_link
*link
)
2187 /* TCP input state */
2188 return link
->data
.tcp
->state
.in
;
2193 GetStateOut(struct alias_link
*link
)
2195 /* TCP output state */
2196 return link
->data
.tcp
->state
.out
;
2201 GetOriginalAddress(struct alias_link
*link
)
2203 if (link
->src_addr
.s_addr
== INADDR_ANY
)
2204 return aliasAddress
;
2206 return(link
->src_addr
);
2211 GetDestAddress(struct alias_link
*link
)
2213 return(link
->dst_addr
);
2218 GetAliasAddress(struct alias_link
*link
)
2220 if (link
->alias_addr
.s_addr
== INADDR_ANY
)
2221 return aliasAddress
;
2223 return link
->alias_addr
;
2228 GetDefaultAliasAddress()
2230 return aliasAddress
;
2235 SetDefaultAliasAddress(struct in_addr alias_addr
)
2237 aliasAddress
= alias_addr
;
2242 GetOriginalPort(struct alias_link
*link
)
2244 return(link
->src_port
);
2249 GetAliasPort(struct alias_link
*link
)
2251 return(link
->alias_port
);
2256 GetDestPort(struct alias_link
*link
)
2258 return(link
->dst_port
);
2263 SetAckModified(struct alias_link
*link
)
2265 /* Indicate that ACK numbers have been modified in a TCP connection */
2266 link
->data
.tcp
->state
.ack_modified
= 1;
2271 GetProxyAddress(struct alias_link
*link
)
2273 return link
->proxy_addr
;
2278 SetProxyAddress(struct alias_link
*link
, struct in_addr addr
)
2280 link
->proxy_addr
= addr
;
2285 GetProxyPort(struct alias_link
*link
)
2287 return link
->proxy_port
;
2292 SetProxyPort(struct alias_link
*link
, u_short port
)
2294 link
->proxy_port
= port
;
2299 GetAckModified(struct alias_link
*link
)
2301 /* See if ACK numbers have been modified */
2302 return link
->data
.tcp
->state
.ack_modified
;
2307 GetDeltaAckIn(struct ip
*pip
, struct alias_link
*link
)
2310 Find out how much the ACK number has been altered for an incoming
2311 TCP packet. To do this, a circular list of ACK numbers where the TCP
2312 packet size was altered is searched.
2317 int delta
, ack_diff_min
;
2320 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2325 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
2327 struct ack_data_record x
;
2329 x
= link
->data
.tcp
->ack
[i
];
2334 ack_diff
= SeqDiff(x
.ack_new
, ack
);
2337 if (ack_diff_min
>= 0)
2339 if (ack_diff
< ack_diff_min
)
2342 ack_diff_min
= ack_diff
;
2348 ack_diff_min
= ack_diff
;
2358 GetDeltaSeqOut(struct ip
*pip
, struct alias_link
*link
)
2361 Find out how much the sequence number has been altered for an outgoing
2362 TCP packet. To do this, a circular list of ACK numbers where the TCP
2363 packet size was altered is searched.
2368 int delta
, seq_diff_min
;
2371 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2376 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
2378 struct ack_data_record x
;
2380 x
= link
->data
.tcp
->ack
[i
];
2385 seq_diff
= SeqDiff(x
.ack_old
, seq
);
2388 if (seq_diff_min
>= 0)
2390 if (seq_diff
< seq_diff_min
)
2393 seq_diff_min
= seq_diff
;
2399 seq_diff_min
= seq_diff
;
2409 AddSeq(struct ip
*pip
, struct alias_link
*link
, int delta
)
2412 When a TCP packet has been altered in length, save this
2413 information in a circular list. If enough packets have
2414 been altered, then this list will begin to overwrite itself.
2418 struct ack_data_record x
;
2419 int hlen
, tlen
, dlen
;
2422 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2424 hlen
= (pip
->ip_hl
+ tc
->th_off
) << 2;
2425 tlen
= ntohs(pip
->ip_len
);
2428 x
.ack_old
= htonl(ntohl(tc
->th_seq
) + dlen
);
2429 x
.ack_new
= htonl(ntohl(tc
->th_seq
) + dlen
+ delta
);
2433 i
= link
->data
.tcp
->state
.index
;
2434 link
->data
.tcp
->ack
[i
] = x
;
2437 if (i
== N_LINK_TCP_DATA
)
2438 link
->data
.tcp
->state
.index
= 0;
2440 link
->data
.tcp
->state
.index
= i
;
2444 SetExpire(struct alias_link
*link
, int expire
)
2448 link
->flags
&= ~LINK_PERMANENT
;
2451 else if (expire
== -1)
2453 link
->flags
|= LINK_PERMANENT
;
2455 else if (expire
> 0)
2457 link
->expire_time
= expire
;
2462 fprintf(stderr
, "PacketAlias/SetExpire(): ");
2463 fprintf(stderr
, "error in expire parameter\n");
2469 ClearCheckNewLink(void)
2475 SetLastLineCrlfTermed(struct alias_link
*link
, int yes
)
2479 link
->flags
|= LINK_LAST_LINE_CRLF_TERMED
;
2481 link
->flags
&= ~LINK_LAST_LINE_CRLF_TERMED
;
2485 GetLastLineCrlfTermed(struct alias_link
*link
)
2488 return (link
->flags
& LINK_LAST_LINE_CRLF_TERMED
);
2492 SetDestCallId(struct alias_link
*link
, u_int16_t cid
)
2496 link
= ReLink(link
, link
->src_addr
, link
->dst_addr
, link
->alias_addr
,
2497 link
->src_port
, cid
, link
->alias_port
, link
->link_type
);
2502 /* Miscellaneous Functions
2505 InitPacketAliasLog()
2506 UninitPacketAliasLog()
2510 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2511 is called to find and remove timed-out aliasing links. Logic exists
2512 to sweep through the entire table and linked list structure
2515 (prototype in alias_local.h)
2526 * Save system time (seconds) in global variable timeStamp for
2527 * use by other functions. This is done so as not to unnecessarily
2528 * waste timeline by making system calls.
2530 gettimeofday(&tv
, &tz
);
2531 timeStamp
= tv
.tv_sec
;
2533 /* Compute number of spokes (output table link chains) to cover */
2534 n100
= LINK_TABLE_OUT_SIZE
* 100 + houseKeepingResidual
;
2535 n100
*= timeStamp
- lastCleanupTime
;
2536 n100
/= ALIAS_CLEANUP_INTERVAL_SECS
;
2540 /* Handle different cases */
2541 if (n
> ALIAS_CLEANUP_MAX_SPOKES
)
2543 n
= ALIAS_CLEANUP_MAX_SPOKES
;
2544 lastCleanupTime
= timeStamp
;
2545 houseKeepingResidual
= 0;
2548 IncrementalCleanup();
2552 lastCleanupTime
= timeStamp
;
2553 houseKeepingResidual
= n100
- 100*n
;
2556 IncrementalCleanup();
2561 fprintf(stderr
, "PacketAlias/HouseKeeping(): ");
2562 fprintf(stderr
, "something unexpected in time values\n");
2564 lastCleanupTime
= timeStamp
;
2565 houseKeepingResidual
= 0;
2570 /* Init the log file and enable logging */
2572 InitPacketAliasLog(void)
2574 if ((~packetAliasMode
& PKT_ALIAS_LOG
)
2575 && (monitorFile
= fopen("/var/log/alias.log", "w")))
2577 packetAliasMode
|= PKT_ALIAS_LOG
;
2578 fprintf(monitorFile
,
2579 "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2584 /* Close the log-file and disable logging. */
2586 UninitPacketAliasLog(void)
2589 fclose(monitorFile
);
2592 packetAliasMode
&= ~PKT_ALIAS_LOG
;
2600 /* Outside world interfaces
2602 -- "outside world" means other than alias*.c routines --
2604 PacketAliasRedirectPort()
2605 PacketAliasAddServer()
2606 PacketAliasRedirectProto()
2607 PacketAliasRedirectAddr()
2608 PacketAliasRedirectDelete()
2609 PacketAliasSetAddress()
2612 PacketAliasSetMode()
2614 (prototypes in alias.h)
2617 /* Redirection from a specific public addr:port to a
2618 private addr:port */
2620 PacketAliasRedirectPort(struct in_addr src_addr
, u_short src_port
,
2621 struct in_addr dst_addr
, u_short dst_port
,
2622 struct in_addr alias_addr
, u_short alias_port
,
2626 struct alias_link
*link
;
2631 link_type
= LINK_UDP
;
2634 link_type
= LINK_TCP
;
2638 fprintf(stderr
, "PacketAliasRedirectPort(): ");
2639 fprintf(stderr
, "only TCP and UDP protocols allowed\n");
2644 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2645 src_port
, dst_port
, alias_port
,
2650 link
->flags
|= LINK_PERMANENT
;
2655 fprintf(stderr
, "PacketAliasRedirectPort(): "
2656 "call to AddLink() failed\n");
2663 /* Add server to the pool of servers */
2665 PacketAliasAddServer(struct alias_link
*link
, struct in_addr addr
, u_short port
)
2667 struct server
*server
;
2669 server
= malloc(sizeof(struct server
));
2671 if (server
!= NULL
) {
2672 struct server
*head
;
2674 server
->addr
= addr
;
2675 server
->port
= port
;
2677 head
= link
->server
;
2679 server
->next
= server
;
2683 for (s
= head
; s
->next
!= head
; s
= s
->next
);
2685 server
->next
= head
;
2687 link
->server
= server
;
2693 /* Redirect packets of a given IP protocol from a specific
2694 public address to a private address */
2696 PacketAliasRedirectProto(struct in_addr src_addr
,
2697 struct in_addr dst_addr
,
2698 struct in_addr alias_addr
,
2701 struct alias_link
*link
;
2703 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2704 NO_SRC_PORT
, NO_DEST_PORT
, 0,
2709 link
->flags
|= LINK_PERMANENT
;
2714 fprintf(stderr
, "PacketAliasRedirectProto(): "
2715 "call to AddLink() failed\n");
2722 /* Static address translation */
2724 PacketAliasRedirectAddr(struct in_addr src_addr
,
2725 struct in_addr alias_addr
)
2727 struct alias_link
*link
;
2729 link
= AddLink(src_addr
, nullAddress
, alias_addr
,
2735 link
->flags
|= LINK_PERMANENT
;
2740 fprintf(stderr
, "PacketAliasRedirectAddr(): "
2741 "call to AddLink() failed\n");
2750 PacketAliasRedirectDelete(struct alias_link
*link
)
2752 /* This is a dangerous function to put in the API,
2753 because an invalid pointer can crash the program. */
2762 PacketAliasSetAddress(struct in_addr addr
)
2764 if (packetAliasMode
& PKT_ALIAS_RESET_ON_ADDR_CHANGE
2765 && aliasAddress
.s_addr
!= addr
.s_addr
)
2768 aliasAddress
= addr
;
2773 PacketAliasSetTarget(struct in_addr target_addr
)
2775 targetAddress
= target_addr
;
2780 PacketAliasInit(void)
2785 static int firstCall
= 1;
2789 gettimeofday(&tv
, &tz
);
2790 timeStamp
= tv
.tv_sec
;
2791 lastCleanupTime
= tv
.tv_sec
;
2792 houseKeepingResidual
= 0;
2794 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
2795 LIST_INIT(&linkTableOut
[i
]);
2796 for (i
=0; i
<LINK_TABLE_IN_SIZE
; i
++)
2797 LIST_INIT(&linkTableIn
[i
]);
2799 atexit(PacketAliasUninit
);
2809 aliasAddress
.s_addr
= INADDR_ANY
;
2810 targetAddress
.s_addr
= INADDR_ANY
;
2817 fragmentIdLinkCount
= 0;
2818 fragmentPtrLinkCount
= 0;
2823 packetAliasMode
= PKT_ALIAS_SAME_PORTS
2824 | PKT_ALIAS_USE_SOCKETS
2825 | PKT_ALIAS_RESET_ON_ADDR_CHANGE
;
2829 PacketAliasUninit(void) {
2833 UninitPacketAliasLog();
2840 /* Change mode for some operations */
2843 unsigned int flags
, /* Which state to bring flags to */
2844 unsigned int mask
/* Mask of which flags to affect (use 0 to do a
2845 probe for flag values) */
2848 /* Enable logging? */
2849 if (flags
& mask
& PKT_ALIAS_LOG
)
2851 InitPacketAliasLog(); /* Do the enable */
2853 /* _Disable_ logging? */
2854 if (~flags
& mask
& PKT_ALIAS_LOG
) {
2855 UninitPacketAliasLog();
2859 /* Start punching holes in the firewall? */
2860 if (flags
& mask
& PKT_ALIAS_PUNCH_FW
) {
2863 /* Stop punching holes in the firewall? */
2864 if (~flags
& mask
& PKT_ALIAS_PUNCH_FW
) {
2869 /* Other flags can be set/cleared without special action */
2870 packetAliasMode
= (flags
& mask
) | (packetAliasMode
& ~mask
);
2871 return packetAliasMode
;
2876 PacketAliasCheckNewLink(void)
2878 return newDefaultLink
;
2885 Code to support firewall punching. This shouldn't really be in this
2886 file, but making variables global is evil too.
2889 /* Firewall include files */
2891 #include <netinet/ip_fw.h>
2895 static void ClearAllFWHoles(void);
2897 static int fireWallBaseNum
; /* The first firewall entry free for our use */
2898 static int fireWallNumNums
; /* How many entries can we use? */
2899 static int fireWallActiveNum
; /* Which entry did we last use? */
2900 static char *fireWallField
; /* bool array for entries */
2902 #define fw_setfield(field, num) \
2904 (field)[(num) - fireWallBaseNum] = 1; \
2905 } /*lint -save -e717 */ while(0) /*lint -restore */
2906 #define fw_clrfield(field, num) \
2908 (field)[(num) - fireWallBaseNum] = 0; \
2909 } /*lint -save -e717 */ while(0) /*lint -restore */
2910 #define fw_tstfield(field, num) ((field)[(num) - fireWallBaseNum])
2914 fireWallField
= malloc(fireWallNumNums
);
2915 if (fireWallField
) {
2916 memset(fireWallField
, 0, fireWallNumNums
);
2917 if (fireWallFD
< 0) {
2918 fireWallFD
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
2921 fireWallActiveNum
= fireWallBaseNum
;
2926 UninitPunchFW(void) {
2928 if (fireWallFD
>= 0)
2932 free(fireWallField
);
2933 fireWallField
= NULL
;
2934 packetAliasMode
&= ~PKT_ALIAS_PUNCH_FW
;
2937 /* Make a certain link go through the firewall */
2939 PunchFWHole(struct alias_link
*link
) {
2940 int r
; /* Result code */
2941 struct ip_fw rule
; /* On-the-fly built rule */
2942 int fwhole
; /* Where to punch hole */
2944 /* Don't do anything unless we are asked to */
2945 if ( !(packetAliasMode
& PKT_ALIAS_PUNCH_FW
) ||
2947 link
->link_type
!= LINK_TCP
)
2950 memset(&rule
, 0, sizeof rule
);
2954 /* Find empty slot */
2955 for (fwhole
= fireWallActiveNum
;
2956 fwhole
< fireWallBaseNum
+ fireWallNumNums
&&
2957 fw_tstfield(fireWallField
, fwhole
);
2960 if (fwhole
== fireWallBaseNum
+ fireWallNumNums
) {
2961 for (fwhole
= fireWallBaseNum
;
2962 fwhole
< fireWallActiveNum
&&
2963 fw_tstfield(fireWallField
, fwhole
);
2966 if (fwhole
== fireWallActiveNum
) {
2967 /* No rule point empty - we can't punch more holes. */
2968 fireWallActiveNum
= fireWallBaseNum
;
2970 fprintf(stderr
, "libalias: Unable to create firewall hole!\n");
2975 /* Start next search at next position */
2976 fireWallActiveNum
= fwhole
+1;
2978 /* Build generic part of the two rules */
2979 rule
.fw_number
= fwhole
;
2980 IP_FW_SETNSRCP(&rule
, 1); /* Number of source ports. */
2981 IP_FW_SETNDSTP(&rule
, 1); /* Number of destination ports. */
2982 rule
.fw_flg
= IP_FW_F_ACCEPT
| IP_FW_F_IN
| IP_FW_F_OUT
;
2983 rule
.fw_prot
= IPPROTO_TCP
;
2984 rule
.fw_smsk
.s_addr
= INADDR_BROADCAST
;
2985 rule
.fw_dmsk
.s_addr
= INADDR_BROADCAST
;
2987 /* Build and apply specific part of the rules */
2988 rule
.fw_src
= GetOriginalAddress(link
);
2989 rule
.fw_dst
= GetDestAddress(link
);
2990 rule
.fw_uar
.fw_pts
[0] = ntohs(GetOriginalPort(link
));
2991 rule
.fw_uar
.fw_pts
[1] = ntohs(GetDestPort(link
));
2993 /* Skip non-bound links - XXX should not be strictly necessary,
2994 but seems to leave hole if not done. Leak of non-bound links?
2995 (Code should be left even if the problem is fixed - it is a
2996 clear optimization) */
2997 if (rule
.fw_uar
.fw_pts
[0] != 0 && rule
.fw_uar
.fw_pts
[1] != 0) {
2998 r
= setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_ADD
, &rule
, sizeof rule
);
3001 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
3003 rule
.fw_src
= GetDestAddress(link
);
3004 rule
.fw_dst
= GetOriginalAddress(link
);
3005 rule
.fw_uar
.fw_pts
[0] = ntohs(GetDestPort(link
));
3006 rule
.fw_uar
.fw_pts
[1] = ntohs(GetOriginalPort(link
));
3007 r
= setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_ADD
, &rule
, sizeof rule
);
3010 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
3013 /* Indicate hole applied */
3014 link
->data
.tcp
->fwhole
= fwhole
;
3015 fw_setfield(fireWallField
, fwhole
);
3018 /* Remove a hole in a firewall associated with a particular alias
3019 link. Calling this too often is harmless. */
3021 ClearFWHole(struct alias_link
*link
) {
3022 if (link
->link_type
== LINK_TCP
) {
3023 int fwhole
= link
->data
.tcp
->fwhole
; /* Where is the firewall hole? */
3029 memset(&rule
, 0, sizeof rule
);
3030 rule
.fw_number
= fwhole
;
3031 while (!setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_DEL
, &rule
, sizeof rule
))
3033 fw_clrfield(fireWallField
, fwhole
);
3034 link
->data
.tcp
->fwhole
= -1;
3038 /* Clear out the entire range dedicated to firewall holes. */
3040 ClearAllFWHoles(void) {
3041 struct ip_fw rule
; /* On-the-fly built rule */
3047 memset(&rule
, 0, sizeof rule
);
3048 for (i
= fireWallBaseNum
; i
< fireWallBaseNum
+ fireWallNumNums
; i
++) {
3050 while (!setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_DEL
, &rule
, sizeof rule
))
3053 memset(fireWallField
, 0, fireWallNumNums
);
3058 PacketAliasSetFWBase(unsigned int base
, unsigned int num
) {
3060 fireWallBaseNum
= base
;
3061 fireWallNumNums
= num
;
3069 struct alias_link
*link
;
3071 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
3073 link
= LIST_FIRST(&linkTableOut
[i
]);
3074 while (link
!= NULL
)
3076 struct alias_link
*link_next
;
3077 char src_str
[32], dst_str
[32], alias_str
[32];
3079 snprintf(src_str
, sizeof(src_str
), "%s:%u",
3080 inet_ntoa(link
->src_addr
), ntohs(link
->src_port
));
3081 snprintf(dst_str
, sizeof(dst_str
), "%s:%u",
3082 inet_ntoa(link
->dst_addr
), ntohs(link
->dst_port
));
3083 snprintf(alias_str
, sizeof(alias_str
), "%s:%u",
3084 inet_ntoa(link
->alias_addr
), ntohs(link
->alias_port
));
3086 syslog(LOG_ERR
, " linkTableOut[%d:%d] src= %s dst= %s alias= %s flags= 0x%x linktype= %d ts= %d exp= %d fd= %d",
3087 i
, icount
, src_str
, dst_str
, alias_str
,
3088 link
->flags
, link
->link_type
, link
->timestamp
, link
->expire_time
, link
->sockfd
);
3090 link_next
= LIST_NEXT(link
, list_out
);