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 */
173 #include <sys/queue.h>
174 #include <sys/socket.h>
175 #include <sys/time.h>
176 #include <sys/types.h>
178 /* BSD network include files */
179 #include <netinet/in_systm.h>
180 #include <netinet/in.h>
181 #include <netinet/ip.h>
182 #include <netinet/tcp.h>
183 #include <arpa/inet.h>
186 #include "alias_local.h"
191 Constants (note: constants are also defined
192 near relevant functions or structs)
195 /* Sizes of input and output link tables */
196 #define LINK_TABLE_OUT_SIZE 101
197 #define LINK_TABLE_IN_SIZE 4001
199 /* Parameters used for cleanup of expired links */
200 #define ALIAS_CLEANUP_INTERVAL_SECS 60
201 #define ALIAS_CLEANUP_MAX_SPOKES 30
203 /* Timeouts (in seconds) for different link types */
204 #define ICMP_EXPIRE_TIME 60
205 #define UDP_EXPIRE_TIME 60
206 #define PROTO_EXPIRE_TIME 60
207 #define FRAGMENT_ID_EXPIRE_TIME 10
208 #define FRAGMENT_PTR_EXPIRE_TIME 30
210 /* TCP link expire time for different cases */
211 /* When the link has been used and closed - minimal grace time to
212 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
213 #ifndef TCP_EXPIRE_DEAD
214 # define TCP_EXPIRE_DEAD 10
217 /* When the link has been used and closed on one side - the other side
218 is allowed to still send data */
219 #ifndef TCP_EXPIRE_SINGLEDEAD
220 # define TCP_EXPIRE_SINGLEDEAD 90
223 /* When the link isn't yet up */
224 #ifndef TCP_EXPIRE_INITIAL
225 # define TCP_EXPIRE_INITIAL 300
228 /* When the link is up */
229 #ifndef TCP_EXPIRE_CONNECTED
230 # define TCP_EXPIRE_CONNECTED 86400
234 static int iChatAVHack
= 1;
237 /* Dummy port number codes used for FindLinkIn/Out() and AddLink().
238 These constants can be anything except zero, which indicates an
239 unknown port number. */
241 #define NO_DEST_PORT 1
242 #define NO_SRC_PORT 1
248 The fundamental data structure used in this program is
249 "struct alias_link". Whenever a TCP connection is made,
250 a UDP datagram is sent out, or an ICMP echo request is made,
251 a link record is made (if it has not already been created).
252 The link record is identified by the source address/port
253 and the destination address/port. In the case of an ICMP
254 echo request, the source port is treated as being equivalent
255 with the 16-bit ID number of the ICMP packet.
257 The link record also can store some auxiliary data. For
258 TCP connections that have had sequence and acknowledgment
259 modifications, data space is available to track these changes.
260 A state field is used to keep track in changes to the TCP
261 connection state. ID numbers of fragments can also be
262 stored in the auxiliary space. Pointers to unresolved
263 fragments can also be stored.
265 The link records support two independent chainings. Lookup
266 tables for input and out tables hold the initial pointers
267 the link chains. On input, the lookup table indexes on alias
268 port and link type. On output, the lookup table indexes on
269 source address, destination address, source port, destination
273 struct ack_data_record
/* used to save changes to ACK/sequence numbers */
281 struct tcp_state
/* Information about TCP connection */
283 int in
; /* State for outside -> inside */
284 int out
; /* State for inside -> outside */
285 int index
; /* Index to ACK data array */
286 int ack_modified
; /* Indicates whether ACK and sequence numbers */
290 #define N_LINK_TCP_DATA 3 /* Number of distinct ACK number changes
291 saved for a modified TCP stream */
294 struct tcp_state state
;
295 struct ack_data_record ack
[N_LINK_TCP_DATA
];
296 int fwhole
; /* Which firewall record is used for this hole? */
299 struct server
/* LSNAT server pool (circular list) */
306 struct alias_link
/* Main data structure */
308 struct in_addr src_addr
; /* Address and port information */
309 struct in_addr dst_addr
;
310 struct in_addr alias_addr
;
311 struct in_addr proxy_addr
;
316 struct server
*server
;
318 int link_type
; /* Type of link: TCP, UDP, ICMP, proto, frag */
320 /* values for link_type */
321 #define LINK_ICMP IPPROTO_ICMP
322 #define LINK_UDP IPPROTO_UDP
323 #define LINK_TCP IPPROTO_TCP
324 #define LINK_FRAGMENT_ID (IPPROTO_MAX + 1)
325 #define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2)
326 #define LINK_ADDR (IPPROTO_MAX + 3)
327 #define LINK_PPTP (IPPROTO_MAX + 4)
329 int flags
; /* indicates special characteristics */
332 #define LINK_UNKNOWN_DEST_PORT 0x01
333 #define LINK_UNKNOWN_DEST_ADDR 0x02
334 #define LINK_PERMANENT 0x04
335 #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
336 #define LINK_UNFIREWALLED 0x08
337 #define LINK_LAST_LINE_CRLF_TERMED 0x10
338 #define LINK_CONE 0x20
340 int timestamp
; /* Time link was last accessed */
341 int expire_time
; /* Expire time for link */
343 int sockfd
; /* socket descriptor */
345 LIST_ENTRY(alias_link
) list_out
; /* Linked list of pointers for */
346 LIST_ENTRY(alias_link
) list_in
; /* input and output lookup tables */
348 union /* Auxiliary data */
351 struct in_addr frag_addr
;
362 The global variables listed here are only accessed from
363 within alias_db.c and so are prefixed with the static
367 int packetAliasMode
; /* Mode flags */
368 /* - documented in alias.h */
370 static struct in_addr aliasAddress
; /* Address written onto source */
371 /* field of IP packet. */
373 static struct in_addr targetAddress
; /* IP address incoming packets */
374 /* are sent to if no aliasing */
375 /* link already exists */
377 static struct in_addr nullAddress
; /* Used as a dummy parameter for */
378 /* some function calls */
379 static LIST_HEAD(, alias_link
)
380 linkTableOut
[LINK_TABLE_OUT_SIZE
]; /* Lookup table of pointers to */
381 /* chains of link records. Each */
382 static LIST_HEAD(, alias_link
) /* link record is doubly indexed */
383 linkTableIn
[LINK_TABLE_IN_SIZE
]; /* into input and output lookup */
386 static int icmpLinkCount
; /* Link statistics */
387 static int udpLinkCount
;
388 static int tcpLinkCount
;
389 static int pptpLinkCount
;
390 static int protoLinkCount
;
391 static int fragmentIdLinkCount
;
392 static int fragmentPtrLinkCount
;
393 static int sockCount
;
395 static int cleanupIndex
; /* Index to chain of link table */
396 /* being inspected for old links */
398 static int timeStamp
; /* System time in seconds for */
401 static int lastCleanupTime
; /* Last time IncrementalCleanup() */
404 static int houseKeepingResidual
; /* used by HouseKeeping() */
406 static int deleteAllLinks
; /* If equal to zero, DeleteLink() */
407 /* will not remove permanent links */
409 static FILE *monitorFile
; /* File descriptor for link */
410 /* statistics monitoring file */
412 static int newDefaultLink
; /* Indicates if a new aliasing */
413 /* link has been created after a */
414 /* call to PacketAliasIn/Out(). */
417 static int fireWallFD
= -1; /* File descriptor to be able to */
418 /* control firewall. Opened by */
419 /* PacketAliasSetMode on first */
420 /* setting the PKT_ALIAS_PUNCH_FW */
430 /* Internal utility routines (used only in alias_db.c)
432 Lookup table starting points:
433 StartPointIn() -- link table initial search point for
435 StartPointOut() -- link table initial search point for
439 SeqDiff() -- difference between two TCP sequences
440 ShowAliasStats() -- send alias statistics to a monitor file
444 /* Local prototypes */
445 static u_int
StartPointIn(struct in_addr
, u_short
, int);
447 static u_int
StartPointOut(struct in_addr
, struct in_addr
,
448 u_short
, u_short
, int);
450 static int SeqDiff(u_long
, u_long
);
452 static void ShowAliasStats(void);
455 /* Firewall control */
456 static void InitPunchFW(void);
457 static void UninitPunchFW(void);
458 static void ClearFWHole(struct alias_link
*link
);
461 /* Log file control */
462 static void InitPacketAliasLog(void);
463 static void UninitPacketAliasLog(void);
466 StartPointIn(struct in_addr alias_addr
,
472 n
= alias_addr
.s_addr
;
473 if (link_type
!= LINK_PPTP
)
476 return(n
% LINK_TABLE_IN_SIZE
);
481 StartPointOut(struct in_addr src_addr
, struct in_addr dst_addr
,
482 u_short src_port
, u_short dst_port
, int link_type
)
487 n
+= dst_addr
.s_addr
;
488 if (link_type
!= LINK_PPTP
) {
494 return(n
% LINK_TABLE_OUT_SIZE
);
499 SeqDiff(u_long x
, u_long y
)
501 /* Return the difference between two TCP sequence numbers */
504 This function is encapsulated in case there are any unusual
505 arithmetic conditions that need to be considered.
508 return (ntohl(y
) - ntohl(x
));
515 /* Used for debugging */
519 fprintf(monitorFile
, "icmp=%d, udp=%d, tcp=%d, pptp=%d, proto=%d, frag_id=%d frag_ptr=%d",
526 fragmentPtrLinkCount
);
528 fprintf(monitorFile
, " / tot=%d (sock=%d)\n",
529 icmpLinkCount
+ udpLinkCount
533 + fragmentIdLinkCount
534 + fragmentPtrLinkCount
,
545 /* Internal routines for finding, deleting and adding links
548 GetNewPort() -- find and reserve new alias port number
549 GetSocket() -- try to allocate a socket for a given port
551 Link creation and deletion:
552 CleanupAliasData() - remove all link chains from lookup table
553 IncrementalCleanup() - look for stale links in a single chain
554 DeleteLink() - remove link
556 ReLink() - change link
559 FindLinkOut() - find link for outgoing packets
560 FindLinkIn() - find link for incoming packets
563 FindNewPortGroup() - find an available group of ports
566 /* Local prototypes */
567 static int GetNewPort(struct alias_link
*, int);
569 static u_short
GetSocket(u_short
, int *, int);
571 static void CleanupAliasData(void);
573 static void IncrementalCleanup(void);
575 static void DeleteLink(struct alias_link
*);
577 static struct alias_link
*
578 AddLink(struct in_addr
, struct in_addr
, struct in_addr
,
579 u_short
, u_short
, int, int);
581 static struct alias_link
*
582 ReLink(struct alias_link
*,
583 struct in_addr
, struct in_addr
, struct in_addr
,
584 u_short
, u_short
, int, int);
586 static struct alias_link
*
587 FindLinkOut(struct in_addr
, struct in_addr
, u_short
, u_short
, int, int);
589 static struct alias_link
*
590 FindLinkIn(struct in_addr
, struct in_addr
, u_short
, u_short
, int, int);
593 #define ALIAS_PORT_BASE 0x08000
594 #define ALIAS_PORT_MASK 0x07fff
595 #define ALIAS_PORT_MASK_EVEN 0x07ffe
596 #define GET_NEW_PORT_MAX_ATTEMPTS 20
598 #define GET_ALIAS_PORT -1
599 #define GET_ALIAS_ID GET_ALIAS_PORT
601 #define FIND_EVEN_ALIAS_BASE 1
603 /* GetNewPort() allocates port numbers. Note that if a port number
604 is already in use, that does not mean that it cannot be used by
605 another link concurrently. This is because GetNewPort() looks for
606 unused triplets: (dest addr, dest port, alias port). */
609 GetNewPort(struct alias_link
*link
, int alias_port_param
)
617 Description of alias_port_param for GetNewPort(). When
618 this parameter is zero or positive, it precisely specifies
619 the port number. GetNewPort() will return this number
620 without check that it is in use.
622 When this parameter is GET_ALIAS_PORT, it indicates to get a randomly
623 selected port number.
625 if (alias_port_param
== GET_ALIAS_PORT
)
628 * The aliasing port is automatically selected
629 * by one of two methods below:
631 max_trials
= GET_NEW_PORT_MAX_ATTEMPTS
;
633 if (packetAliasMode
& PKT_ALIAS_SAME_PORTS
)
636 * When the PKT_ALIAS_SAME_PORTS option is
637 * chosen, the first try will be the
638 * actual source port. If this is already
639 * in use, the remainder of the trials
642 port_net
= link
->src_port
;
643 port_sys
= ntohs(port_net
);
647 /* First trial and all subsequent are random. */
648 port_sys
= random() & ALIAS_PORT_MASK
;
649 port_sys
+= ALIAS_PORT_BASE
;
650 port_net
= htons(port_sys
);
653 else if (alias_port_param
>= 0 && alias_port_param
< 0x10000)
655 link
->alias_port
= (u_short
) alias_port_param
;
661 fprintf(stderr
, "PacketAlias/GetNewPort(): ");
662 fprintf(stderr
, "input parameter error\n");
668 /* Port number search */
669 for (i
=0; i
<max_trials
; i
++)
672 struct alias_link
*search_result
;
674 search_result
= FindLinkIn(link
->dst_addr
, link
->alias_addr
,
675 link
->dst_port
, port_net
,
678 if (search_result
== NULL
)
680 else if (!(link
->flags
& LINK_PARTIALLY_SPECIFIED
)
681 && (search_result
->flags
& LINK_PARTIALLY_SPECIFIED
))
688 if ((packetAliasMode
& PKT_ALIAS_USE_SOCKETS
)
689 && (link
->flags
& LINK_PARTIALLY_SPECIFIED
)
690 && ((link
->link_type
== LINK_TCP
) ||
691 (link
->link_type
== LINK_UDP
)))
693 if (GetSocket(port_net
, &link
->sockfd
, link
->link_type
))
695 link
->alias_port
= port_net
;
701 link
->alias_port
= port_net
;
706 port_sys
= random() & ALIAS_PORT_MASK
;
707 port_sys
+= ALIAS_PORT_BASE
;
708 port_net
= htons(port_sys
);
711 fprintf(stderr
, "PacketAlias/GetnewPort(): ");
712 fprintf(stderr
, "could not find free port\n");
720 GetSocket(u_short port_net
, int *sockfd
, int link_type
)
724 struct sockaddr_in sock_addr
;
726 if (link_type
== LINK_TCP
)
727 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
728 else if (link_type
== LINK_UDP
)
729 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
733 fprintf(stderr
, "PacketAlias/GetSocket(): ");
734 fprintf(stderr
, "incorrect link type\n");
742 fprintf(stderr
, "PacketAlias/GetSocket(): ");
743 fprintf(stderr
, "socket() error %d\n", *sockfd
);
748 sock_addr
.sin_family
= AF_INET
;
749 sock_addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
750 sock_addr
.sin_port
= port_net
;
753 (struct sockaddr
*) &sock_addr
,
769 /* FindNewPortGroup() returns a base port number for an available
770 range of contiguous port numbers. Note that if a port number
771 is already in use, that does not mean that it cannot be used by
772 another link concurrently. This is because FindNewPortGroup()
773 looks for unused triplets: (dest addr, dest port, alias port). */
776 FindNewPortGroup(struct in_addr dst_addr
,
777 struct in_addr alias_addr
,
790 * Get link_type from protocol
796 link_type
= LINK_UDP
;
799 link_type
= LINK_TCP
;
807 * The aliasing port is automatically selected
808 * by one of two methods below:
810 max_trials
= GET_NEW_PORT_MAX_ATTEMPTS
;
812 if (packetAliasMode
& PKT_ALIAS_SAME_PORTS
) {
814 * When the ALIAS_SAME_PORTS option is
815 * chosen, the first try will be the
816 * actual source port. If this is already
817 * in use, the remainder of the trials
820 port_sys
= ntohs(src_port
);
824 /* First trial and all subsequent are random. */
825 if (align
== FIND_EVEN_ALIAS_BASE
)
826 port_sys
= random() & ALIAS_PORT_MASK_EVEN
;
828 port_sys
= random() & ALIAS_PORT_MASK
;
830 port_sys
+= ALIAS_PORT_BASE
;
833 /* Port number search */
834 for (i
= 0; i
< max_trials
; i
++) {
836 struct alias_link
*search_result
;
838 for (j
= 0; j
< port_count
; j
++)
839 if (0 != (search_result
= FindLinkIn(dst_addr
, alias_addr
,
840 dst_port
, htons(port_sys
+ j
),
844 /* Found a good range, return base */
846 return (htons(port_sys
));
848 /* Find a new base to try */
849 if (align
== FIND_EVEN_ALIAS_BASE
)
850 port_sys
= random() & ALIAS_PORT_MASK_EVEN
;
852 port_sys
= random() & ALIAS_PORT_MASK
;
854 port_sys
+= ALIAS_PORT_BASE
;
858 fprintf(stderr
, "PacketAlias/FindNewPortGroup(): ");
859 fprintf(stderr
, "could not find free port(s)\n");
866 CleanupAliasData(void)
868 struct alias_link
*link
;
872 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
874 link
= LIST_FIRST(&linkTableOut
[i
]);
877 struct alias_link
*link_next
;
878 link_next
= LIST_NEXT(link
, list_out
);
890 IncrementalCleanup(void)
893 struct alias_link
*link
;
896 link
= LIST_FIRST(&linkTableOut
[cleanupIndex
++]);
900 struct alias_link
*link_next
;
902 link_next
= LIST_NEXT(link
, list_out
);
903 idelta
= timeStamp
- link
->timestamp
;
904 switch (link
->link_type
)
907 if (idelta
> link
->expire_time
)
909 struct tcp_dat
*tcp_aux
;
911 tcp_aux
= link
->data
.tcp
;
912 if (tcp_aux
->state
.in
!= ALIAS_TCP_STATE_CONNECTED
913 || tcp_aux
->state
.out
!= ALIAS_TCP_STATE_CONNECTED
)
921 if (idelta
> link
->expire_time
)
931 if (cleanupIndex
== LINK_TABLE_OUT_SIZE
)
936 DeleteLink(struct alias_link
*link
)
939 /* Don't do anything if the link is marked permanent */
940 if (deleteAllLinks
== 0 && link
->flags
& LINK_PERMANENT
)
944 /* Delete associated firewall hole, if any */
948 /* Free memory allocated for LSNAT server pool */
949 if (link
->server
!= NULL
) {
950 struct server
*head
, *curr
, *next
;
952 head
= curr
= link
->server
;
956 } while ((curr
= next
) != head
);
959 /* Adjust output table pointers */
960 LIST_REMOVE(link
, list_out
);
962 /* Adjust input table pointers */
963 LIST_REMOVE(link
, list_in
);
965 /* Close socket, if one has been allocated */
966 if (link
->sockfd
!= -1)
972 /* Link-type dependent cleanup */
973 switch(link
->link_type
)
983 free(link
->data
.tcp
);
988 case LINK_FRAGMENT_ID
:
989 fragmentIdLinkCount
--;
991 case LINK_FRAGMENT_PTR
:
992 fragmentPtrLinkCount
--;
993 if (link
->data
.frag_ptr
!= NULL
)
994 free(link
->data
.frag_ptr
);
1004 if ((packetAliasMode
& PKT_ALIAS_LOG
) != 0 &&
1005 !IN_MULTICAST(link
->src_addr
.s_addr
) &&
1006 !IN_MULTICAST(link
->dst_addr
.s_addr
))
1012 switch(link
->link_type
)
1023 fprintf(monitorFile
, "Deleted%s %s:%d<->%s:%d to %s:%d<->%s:%d\n",
1025 inet_ntop(AF_INET
, &link
->src_addr
, src
, sizeof(src
)), link
->src_port
,
1026 inet_ntop(AF_INET
, &link
->dst_addr
, dst
, sizeof(dst
)), link
->dst_port
,
1027 inet_ntop(AF_INET
, &link
->alias_addr
, alias
, sizeof(alias
)), link
->alias_port
,
1028 dst
, link
->dst_port
);
1029 fflush(monitorFile
);
1032 if (packetAliasMode
& PKT_ALIAS_LOG
)
1041 static struct alias_link
*
1042 AddLink(struct in_addr src_addr
,
1043 struct in_addr dst_addr
,
1044 struct in_addr alias_addr
,
1047 int alias_port_param
, /* if less than zero, alias */
1048 int link_type
) /* port will be automatically */
1049 { /* chosen. If greater than */
1050 u_int start_point
; /* zero, equal to alias port */
1051 struct alias_link
*link
;
1053 link
= malloc(sizeof(struct alias_link
));
1056 /* Basic initialization */
1057 link
->src_addr
= src_addr
;
1058 link
->dst_addr
= dst_addr
;
1059 link
->alias_addr
= alias_addr
;
1060 link
->proxy_addr
.s_addr
= INADDR_ANY
;
1061 link
->src_port
= src_port
;
1062 link
->dst_port
= dst_port
;
1063 link
->proxy_port
= 0;
1064 link
->server
= NULL
;
1065 link
->link_type
= link_type
;
1068 link
->timestamp
= timeStamp
;
1070 /* Expiration time */
1074 link
->expire_time
= ICMP_EXPIRE_TIME
;
1077 if (dst_addr
.s_addr
== 0 && dst_port
== 0)
1078 link
->expire_time
= UDP_EXPIRE_TIME
* 5;
1080 link
->expire_time
= UDP_EXPIRE_TIME
;
1083 link
->expire_time
= TCP_EXPIRE_INITIAL
;
1086 link
->flags
|= LINK_PERMANENT
; /* no timeout. */
1088 case LINK_FRAGMENT_ID
:
1089 link
->expire_time
= FRAGMENT_ID_EXPIRE_TIME
;
1091 case LINK_FRAGMENT_PTR
:
1092 link
->expire_time
= FRAGMENT_PTR_EXPIRE_TIME
;
1097 link
->expire_time
= PROTO_EXPIRE_TIME
;
1101 /* Determine alias flags */
1102 if (dst_addr
.s_addr
== INADDR_ANY
)
1103 link
->flags
|= LINK_UNKNOWN_DEST_ADDR
;
1105 link
->flags
|= LINK_UNKNOWN_DEST_PORT
;
1107 /* Determine alias port */
1108 if (GetNewPort(link
, alias_port_param
) != 0)
1113 /* Link-type dependent initialization */
1116 struct tcp_dat
*aux_tcp
;
1125 aux_tcp
= malloc(sizeof(struct tcp_dat
));
1126 if (aux_tcp
!= NULL
)
1131 aux_tcp
->state
.in
= ALIAS_TCP_STATE_NOT_CONNECTED
;
1132 aux_tcp
->state
.out
= ALIAS_TCP_STATE_NOT_CONNECTED
;
1133 aux_tcp
->state
.index
= 0;
1134 aux_tcp
->state
.ack_modified
= 0;
1135 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
1136 aux_tcp
->ack
[i
].active
= 0;
1137 aux_tcp
->fwhole
= -1;
1138 link
->data
.tcp
= aux_tcp
;
1143 fprintf(stderr
, "PacketAlias/AddLink: ");
1144 fprintf(stderr
, " cannot allocate auxiliary TCP data\n");
1153 case LINK_FRAGMENT_ID
:
1154 fragmentIdLinkCount
++;
1156 case LINK_FRAGMENT_PTR
:
1157 fragmentPtrLinkCount
++;
1166 /* Set up pointers for output lookup table */
1167 start_point
= StartPointOut(src_addr
, dst_addr
,
1168 src_port
, dst_port
, link_type
);
1169 LIST_INSERT_HEAD(&linkTableOut
[start_point
], link
, list_out
);
1171 /* Set up pointers for input lookup table */
1172 start_point
= StartPointIn(alias_addr
, link
->alias_port
, link_type
);
1173 LIST_INSERT_HEAD(&linkTableIn
[start_point
], link
, list_in
);
1178 fprintf(stderr
, "PacketAlias/AddLink(): ");
1179 fprintf(stderr
, "malloc() call failed.\n");
1184 if ((packetAliasMode
& PKT_ALIAS_LOG
) != 0 &&
1185 !IN_MULTICAST(link
->src_addr
.s_addr
) &&
1186 !IN_MULTICAST(link
->dst_addr
.s_addr
))
1192 switch(link
->link_type
)
1203 fprintf(monitorFile
, "Added %s %s:%d<->%s:%d to %s:%d<->%s:%d\n",
1205 inet_ntop(AF_INET
, &link
->src_addr
, src
, sizeof(src
)), link
->src_port
,
1206 inet_ntop(AF_INET
, &link
->dst_addr
, dst
, sizeof(dst
)), link
->dst_port
,
1207 inet_ntop(AF_INET
, &link
->alias_addr
, alias
, sizeof(alias
)), link
->alias_port
,
1208 dst
, link
->dst_port
);
1211 if (packetAliasMode
& PKT_ALIAS_LOG
)
1218 static struct alias_link
*
1219 ReLink(struct alias_link
*old_link
,
1220 struct in_addr src_addr
,
1221 struct in_addr dst_addr
,
1222 struct in_addr alias_addr
,
1225 int alias_port_param
, /* if less than zero, alias */
1226 int link_type
) /* port will be automatically */
1227 { /* chosen. If greater than */
1228 struct alias_link
*new_link
; /* zero, equal to alias port */
1230 new_link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1231 src_port
, dst_port
, alias_port_param
,
1234 if (new_link
!= NULL
&&
1235 old_link
->link_type
== LINK_TCP
&&
1236 old_link
->data
.tcp
->fwhole
> 0) {
1237 PunchFWHole(new_link
);
1240 if ((old_link
->flags
& LINK_CONE
) == 0)
1241 DeleteLink(old_link
);
1245 static struct alias_link
*
1246 _FindLinkOut(struct in_addr src_addr
,
1247 struct in_addr dst_addr
,
1251 int replace_partial_links
)
1254 struct alias_link
*link
;
1256 i
= StartPointOut(src_addr
, dst_addr
, src_port
, dst_port
, link_type
);
1257 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1259 if (link
->src_addr
.s_addr
== src_addr
.s_addr
1260 && link
->server
== NULL
1261 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
1262 && link
->dst_port
== dst_port
1263 && link
->src_port
== src_port
1264 && link
->link_type
== link_type
)
1266 link
->timestamp
= timeStamp
;
1271 /* Search for partially specified links. */
1272 if (link
== NULL
&& replace_partial_links
)
1274 if (dst_port
!= 0 && dst_addr
.s_addr
!= INADDR_ANY
)
1276 link
= _FindLinkOut(src_addr
, dst_addr
, src_port
, 0,
1279 link
= _FindLinkOut(src_addr
, nullAddress
, src_port
,
1280 dst_port
, link_type
, 0);
1283 (dst_port
!= 0 || dst_addr
.s_addr
!= INADDR_ANY
))
1285 link
= _FindLinkOut(src_addr
, nullAddress
, src_port
, 0,
1291 src_addr
, dst_addr
, link
->alias_addr
,
1292 src_port
, dst_port
, link
->alias_port
,
1300 static struct alias_link
*
1301 FindLinkOut(struct in_addr src_addr
,
1302 struct in_addr dst_addr
,
1306 int replace_partial_links
)
1308 struct alias_link
*link
;
1310 link
= _FindLinkOut(src_addr
, dst_addr
, src_port
, dst_port
,
1311 link_type
, replace_partial_links
);
1315 /* The following allows permanent links to be
1316 specified as using the default source address
1317 (i.e. device interface address) without knowing
1318 in advance what that address is. */
1319 if (aliasAddress
.s_addr
!= 0 &&
1320 src_addr
.s_addr
== aliasAddress
.s_addr
)
1322 link
= _FindLinkOut(nullAddress
, dst_addr
, src_port
, dst_port
,
1323 link_type
, replace_partial_links
);
1331 static struct alias_link
*
1332 _FindLinkIn(struct in_addr dst_addr
,
1333 struct in_addr alias_addr
,
1337 int replace_partial_links
)
1341 struct alias_link
*link
;
1342 struct alias_link
*link_fully_specified
;
1343 struct alias_link
*link_unknown_all
;
1344 struct alias_link
*link_unknown_dst_addr
;
1345 struct alias_link
*link_unknown_dst_port
;
1347 /* Initialize pointers */
1348 link_fully_specified
= NULL
;
1349 link_unknown_all
= NULL
;
1350 link_unknown_dst_addr
= NULL
;
1351 link_unknown_dst_port
= NULL
;
1353 /* If either the dest addr or port is unknown, the search
1354 loop will have to know about this. */
1357 if (dst_addr
.s_addr
== INADDR_ANY
)
1358 flags_in
|= LINK_UNKNOWN_DEST_ADDR
;
1360 flags_in
|= LINK_UNKNOWN_DEST_PORT
;
1363 start_point
= StartPointIn(alias_addr
, alias_port
, link_type
);
1364 LIST_FOREACH(link
, &linkTableIn
[start_point
], list_in
)
1368 flags
= flags_in
| link
->flags
;
1369 if (!(flags
& LINK_PARTIALLY_SPECIFIED
))
1371 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1372 && link
->alias_port
== alias_port
1373 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
1374 && link
->dst_port
== dst_port
1375 && link
->link_type
== link_type
)
1377 link_fully_specified
= link
;
1381 else if ((flags
& LINK_UNKNOWN_DEST_ADDR
)
1382 && (flags
& LINK_UNKNOWN_DEST_PORT
))
1384 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1385 && link
->alias_port
== alias_port
1386 && link
->link_type
== link_type
)
1388 if (link_unknown_all
== NULL
)
1389 link_unknown_all
= link
;
1392 else if (flags
& LINK_UNKNOWN_DEST_ADDR
)
1394 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1395 && link
->alias_port
== alias_port
1396 && link
->link_type
== link_type
1397 && link
->dst_port
== dst_port
)
1399 if (link_unknown_dst_addr
== NULL
)
1400 link_unknown_dst_addr
= link
;
1403 else if (flags
& LINK_UNKNOWN_DEST_PORT
)
1405 if (link
->alias_addr
.s_addr
== alias_addr
.s_addr
1406 && link
->alias_port
== alias_port
1407 && link
->link_type
== link_type
1408 && link
->dst_addr
.s_addr
== dst_addr
.s_addr
)
1410 if (link_unknown_dst_port
== NULL
)
1411 link_unknown_dst_port
= link
;
1418 if (link_fully_specified
!= NULL
)
1420 link_fully_specified
->timestamp
= timeStamp
;
1421 link
= link_fully_specified
;
1423 else if (link_unknown_dst_port
!= NULL
)
1424 link
= link_unknown_dst_port
;
1425 else if (link_unknown_dst_addr
!= NULL
)
1426 link
= link_unknown_dst_addr
;
1427 else if (link_unknown_all
!= NULL
)
1428 link
= link_unknown_all
;
1432 if (replace_partial_links
&&
1433 (link
->flags
& LINK_PARTIALLY_SPECIFIED
|| link
->server
!= NULL
))
1435 struct in_addr src_addr
;
1438 if (link
->server
!= NULL
) { /* LSNAT link */
1439 src_addr
= link
->server
->addr
;
1440 src_port
= link
->server
->port
;
1441 link
->server
= link
->server
->next
;
1443 src_addr
= link
->src_addr
;
1444 src_port
= link
->src_port
;
1448 src_addr
, dst_addr
, alias_addr
,
1449 src_port
, dst_port
, alias_port
,
1456 static struct alias_link
*
1457 FindLinkIn(struct in_addr dst_addr
,
1458 struct in_addr alias_addr
,
1462 int replace_partial_links
)
1464 struct alias_link
*link
;
1466 link
= _FindLinkIn(dst_addr
, alias_addr
, dst_port
, alias_port
,
1467 link_type
, replace_partial_links
);
1471 /* The following allows permanent links to be
1472 specified as using the default aliasing address
1473 (i.e. device interface address) without knowing
1474 in advance what that address is. */
1475 if (aliasAddress
.s_addr
!= 0 &&
1476 alias_addr
.s_addr
== aliasAddress
.s_addr
)
1478 link
= _FindLinkIn(dst_addr
, nullAddress
, dst_port
, alias_port
,
1479 link_type
, replace_partial_links
);
1489 /* External routines for finding/adding links
1491 -- "external" means outside alias_db.c, but within alias*.c --
1493 FindIcmpIn(), FindIcmpOut()
1494 FindFragmentIn1(), FindFragmentIn2()
1495 AddFragmentPtrLink(), FindFragmentPtr()
1496 FindProtoIn(), FindProtoOut()
1497 FindUdpTcpIn(), FindUdpTcpOut()
1498 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
1499 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
1500 FindOriginalAddress(), FindAliasAddress()
1502 (prototypes in alias_local.h)
1507 FindIcmpIn(struct in_addr dst_addr
,
1508 struct in_addr alias_addr
,
1512 struct alias_link
*link
;
1514 link
= FindLinkIn(dst_addr
, alias_addr
,
1515 NO_DEST_PORT
, id_alias
,
1517 if (link
== NULL
&& create
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1519 struct in_addr target_addr
;
1521 target_addr
= FindOriginalAddress(alias_addr
);
1522 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1523 id_alias
, NO_DEST_PORT
, id_alias
,
1532 FindIcmpOut(struct in_addr src_addr
,
1533 struct in_addr dst_addr
,
1537 struct alias_link
* link
;
1539 link
= FindLinkOut(src_addr
, dst_addr
,
1542 if (link
== NULL
&& create
)
1544 struct in_addr alias_addr
;
1546 alias_addr
= FindAliasAddress(src_addr
);
1547 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1548 id
, NO_DEST_PORT
, GET_ALIAS_ID
,
1557 FindFragmentIn1(struct in_addr dst_addr
,
1558 struct in_addr alias_addr
,
1561 struct alias_link
*link
;
1563 link
= FindLinkIn(dst_addr
, alias_addr
,
1564 NO_DEST_PORT
, ip_id
,
1565 LINK_FRAGMENT_ID
, 0);
1569 link
= AddLink(nullAddress
, dst_addr
, alias_addr
,
1570 NO_SRC_PORT
, NO_DEST_PORT
, ip_id
,
1579 FindFragmentIn2(struct in_addr dst_addr
, /* Doesn't add a link if one */
1580 struct in_addr alias_addr
, /* is not found. */
1583 return FindLinkIn(dst_addr
, alias_addr
,
1584 NO_DEST_PORT
, ip_id
,
1585 LINK_FRAGMENT_ID
, 0);
1590 AddFragmentPtrLink(struct in_addr dst_addr
,
1593 return AddLink(nullAddress
, dst_addr
, nullAddress
,
1594 NO_SRC_PORT
, NO_DEST_PORT
, ip_id
,
1600 FindFragmentPtr(struct in_addr dst_addr
,
1603 return FindLinkIn(dst_addr
, nullAddress
,
1604 NO_DEST_PORT
, ip_id
,
1605 LINK_FRAGMENT_PTR
, 0);
1610 FindProtoIn(struct in_addr dst_addr
,
1611 struct in_addr alias_addr
,
1614 struct alias_link
*link
;
1616 link
= FindLinkIn(dst_addr
, alias_addr
,
1620 if (link
== NULL
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1622 struct in_addr target_addr
;
1624 target_addr
= FindOriginalAddress(alias_addr
);
1625 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1626 NO_SRC_PORT
, NO_DEST_PORT
, 0,
1635 FindProtoOut(struct in_addr src_addr
,
1636 struct in_addr dst_addr
,
1639 struct alias_link
*link
;
1641 link
= FindLinkOut(src_addr
, dst_addr
,
1642 NO_SRC_PORT
, NO_DEST_PORT
,
1647 struct in_addr alias_addr
;
1649 alias_addr
= FindAliasAddress(src_addr
);
1650 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1651 NO_SRC_PORT
, NO_DEST_PORT
, 0,
1660 FindUdpTcpIn(struct in_addr dst_addr
,
1661 struct in_addr alias_addr
,
1668 struct alias_link
*link
;
1673 link_type
= LINK_UDP
;
1676 link_type
= LINK_TCP
;
1683 link
= FindLinkIn(dst_addr
, alias_addr
,
1684 dst_port
, alias_port
,
1687 if (link
== NULL
&& create
&& !(packetAliasMode
& PKT_ALIAS_DENY_INCOMING
))
1689 struct in_addr target_addr
;
1691 target_addr
= FindOriginalAddress(alias_addr
);
1692 link
= AddLink(target_addr
, dst_addr
, alias_addr
,
1693 alias_port
, dst_port
, alias_port
,
1702 FindUdpTcpOut(struct in_addr src_addr
,
1703 struct in_addr dst_addr
,
1710 struct alias_link
*link
;
1715 link_type
= LINK_UDP
;
1718 link_type
= LINK_TCP
;
1725 link
= FindLinkOut(src_addr
, dst_addr
, src_port
, dst_port
, link_type
, create
);
1727 if (link
== NULL
&& create
)
1729 struct in_addr alias_addr
;
1730 struct in_addr dst_addr2
= dst_addr
;
1731 u_short dst_port2
= dst_port
;
1733 alias_addr
= FindAliasAddress(src_addr
);
1735 if (iChatAVHack
&& link_type
== LINK_UDP
&& dst_port
== htons(5678)) {
1736 dst_addr2
.s_addr
= 0;
1739 link
= AddLink(src_addr
, dst_addr2
, alias_addr
,
1740 src_port
, dst_port2
, GET_ALIAS_PORT
,
1743 (link
->flags
& (LINK_UNKNOWN_DEST_ADDR
| LINK_UNKNOWN_DEST_PORT
)) != 0)
1745 link
->flags
|= LINK_CONE
;
1746 link
= ReLink(link
, link
->src_addr
, dst_addr
, link
->alias_addr
,
1747 link
->src_port
, dst_port
, link
->alias_port
, link_type
);
1756 AddPptp(struct in_addr src_addr
,
1757 struct in_addr dst_addr
,
1758 struct in_addr alias_addr
,
1759 u_int16_t src_call_id
)
1761 struct alias_link
*link
;
1763 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1764 src_call_id
, 0, GET_ALIAS_PORT
,
1772 FindPptpOutByCallId(struct in_addr src_addr
,
1773 struct in_addr dst_addr
,
1774 u_int16_t src_call_id
)
1777 struct alias_link
*link
;
1779 i
= StartPointOut(src_addr
, dst_addr
, 0, 0, LINK_PPTP
);
1780 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1781 if (link
->link_type
== LINK_PPTP
&&
1782 link
->src_addr
.s_addr
== src_addr
.s_addr
&&
1783 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1784 link
->src_port
== src_call_id
)
1792 FindPptpOutByPeerCallId(struct in_addr src_addr
,
1793 struct in_addr dst_addr
,
1794 u_int16_t dst_call_id
)
1797 struct alias_link
*link
;
1799 i
= StartPointOut(src_addr
, dst_addr
, 0, 0, LINK_PPTP
);
1800 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1801 if (link
->link_type
== LINK_PPTP
&&
1802 link
->src_addr
.s_addr
== src_addr
.s_addr
&&
1803 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1804 link
->dst_port
== dst_call_id
)
1812 FindPptpInByCallId(struct in_addr dst_addr
,
1813 struct in_addr alias_addr
,
1814 u_int16_t dst_call_id
)
1817 struct alias_link
*link
;
1819 i
= StartPointIn(alias_addr
, 0, LINK_PPTP
);
1820 LIST_FOREACH(link
, &linkTableIn
[i
], list_in
)
1821 if (link
->link_type
== LINK_PPTP
&&
1822 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1823 link
->alias_addr
.s_addr
== alias_addr
.s_addr
&&
1824 link
->dst_port
== dst_call_id
)
1832 FindPptpInByPeerCallId(struct in_addr dst_addr
,
1833 struct in_addr alias_addr
,
1834 u_int16_t alias_call_id
)
1836 struct alias_link
*link
;
1838 link
= FindLinkIn(dst_addr
, alias_addr
,
1839 0/* any */, alias_call_id
,
1848 FindRtspOut(struct in_addr src_addr
,
1849 struct in_addr dst_addr
,
1855 struct alias_link
*link
;
1860 link_type
= LINK_UDP
;
1863 link_type
= LINK_TCP
;
1870 link
= FindLinkOut(src_addr
, dst_addr
, src_port
, 0, link_type
, 1);
1874 struct in_addr alias_addr
;
1876 alias_addr
= FindAliasAddress(src_addr
);
1877 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
1878 src_port
, 0, alias_port
,
1887 FindOriginalAddress(struct in_addr alias_addr
)
1889 struct alias_link
*link
;
1891 link
= FindLinkIn(nullAddress
, alias_addr
,
1892 0, 0, LINK_ADDR
, 0);
1896 if (targetAddress
.s_addr
== INADDR_ANY
)
1898 else if (targetAddress
.s_addr
== INADDR_NONE
)
1899 return aliasAddress
;
1901 return targetAddress
;
1905 if (link
->server
!= NULL
) { /* LSNAT link */
1906 struct in_addr src_addr
;
1908 src_addr
= link
->server
->addr
;
1909 link
->server
= link
->server
->next
;
1911 } else if (link
->src_addr
.s_addr
== INADDR_ANY
)
1912 return aliasAddress
;
1914 return link
->src_addr
;
1920 FindAliasAddress(struct in_addr original_addr
)
1922 struct alias_link
*link
;
1924 link
= FindLinkOut(original_addr
, nullAddress
,
1925 0, 0, LINK_ADDR
, 0);
1928 return aliasAddress
;
1932 if (link
->alias_addr
.s_addr
== INADDR_ANY
)
1933 return aliasAddress
;
1935 return link
->alias_addr
;
1939 /* FindAliasPortOut */
1940 /* external routine for NatPortMap */
1941 /* return alias port for the src_addr,dst_addr,src_port and proto */
1942 /* if one doesn't existed, create a mapping with providing pub_port if it's not 0 */
1943 /* delete mapping if addmapping is not true */
1945 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
)
1948 struct alias_link
*link
;
1954 link_type
= LINK_UDP
;
1957 link_type
= LINK_TCP
;
1968 printf("PORTMAP::srcaddr = 0x%x.%d, dstaddr = 0x%x.%d link_type = %d, lifetime = %d\n",
1969 src_addr
.s_addr
, src_port
, dst_addr
.s_addr
, pub_port
, link_type
, lifetime
);
1971 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
1973 link
= LIST_FIRST(&linkTableOut
[i
]);
1974 while (link
!= NULL
)
1976 struct alias_link
*link_next
;
1978 printf("PORTMAP:: linksrcaddr = 0x%x.%d, linkdstaddr = 0x%x.%d, aliasaddr=0x%x.%d, linktype = %d\n",
1979 link
->src_addr
.s_addr
,link
->src_port
,link
->dst_addr
.s_addr
,link
->dst_port
, link
->alias_addr
.s_addr
,link
->alias_port
,
1982 link_next
= LIST_NEXT(link
, list_out
);
1991 i
= StartPointOut(src_addr
, dst_addr
, src_port
, 0, link_type
);
1993 printf("PORTMAP::StartPointOut returns %d\n", i
);
1995 LIST_FOREACH(link
, &linkTableOut
[i
], list_out
)
1997 if (link
->src_addr
.s_addr
== src_addr
.s_addr
&&
1998 link
->dst_addr
.s_addr
== dst_addr
.s_addr
&&
1999 link
->src_port
== src_port
&& link
->link_type
== link_type
)
2003 if ( link
== NULL
&& addmapping
)
2005 struct in_addr alias_addr
;
2007 printf("PORTMAP:: cannot find mapping, adding mapping private port =%d, public port = %d\n",src_port
, pub_port
);
2009 /* address/port in not in list, create new mapping */
2011 alias_addr
= FindAliasAddress(src_addr
);
2012 /* create new mapping */
2014 pub_port
= GET_ALIAS_PORT
;
2015 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2016 src_port
, 0, pub_port
,
2019 /* link was create, set new lifetime */
2020 SetExpire(link
, lifetime
);
2025 return( GetAliasPort(link
));
2028 SetExpire(link
, 0); /* delete mapping */
2037 /* External routines for getting or changing link data
2038 (external to alias_db.c, but internal to alias*.c)
2040 SetFragmentData(), GetFragmentData()
2041 SetFragmentPtr(), GetFragmentPtr()
2042 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
2043 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
2044 GetOriginalPort(), GetAliasPort()
2045 SetAckModified(), GetAckModified()
2046 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
2047 SetLastLineCrlfTermed(), GetLastLineCrlfTermed()
2053 SetFragmentAddr(struct alias_link
*link
, struct in_addr src_addr
)
2055 link
->data
.frag_addr
= src_addr
;
2060 GetFragmentAddr(struct alias_link
*link
, struct in_addr
*src_addr
)
2062 *src_addr
= link
->data
.frag_addr
;
2067 SetFragmentPtr(struct alias_link
*link
, char *fptr
)
2069 link
->data
.frag_ptr
= fptr
;
2074 GetFragmentPtr(struct alias_link
*link
, char **fptr
)
2076 *fptr
= link
->data
.frag_ptr
;
2081 SetStateIn(struct alias_link
*link
, int state
)
2083 /* TCP input state */
2085 case ALIAS_TCP_STATE_DISCONNECTED
:
2086 if (link
->data
.tcp
->state
.out
!= ALIAS_TCP_STATE_CONNECTED
)
2087 link
->expire_time
= TCP_EXPIRE_DEAD
;
2089 link
->expire_time
= TCP_EXPIRE_SINGLEDEAD
;
2091 case ALIAS_TCP_STATE_CONNECTED
:
2092 if (link
->data
.tcp
->state
.out
== ALIAS_TCP_STATE_CONNECTED
)
2093 link
->expire_time
= TCP_EXPIRE_CONNECTED
;
2098 link
->data
.tcp
->state
.in
= state
;
2103 SetStateOut(struct alias_link
*link
, int state
)
2105 /* TCP output state */
2107 case ALIAS_TCP_STATE_DISCONNECTED
:
2108 if (link
->data
.tcp
->state
.in
!= ALIAS_TCP_STATE_CONNECTED
)
2109 link
->expire_time
= TCP_EXPIRE_DEAD
;
2111 link
->expire_time
= TCP_EXPIRE_SINGLEDEAD
;
2113 case ALIAS_TCP_STATE_CONNECTED
:
2114 if (link
->data
.tcp
->state
.in
== ALIAS_TCP_STATE_CONNECTED
)
2115 link
->expire_time
= TCP_EXPIRE_CONNECTED
;
2120 link
->data
.tcp
->state
.out
= state
;
2125 GetStateIn(struct alias_link
*link
)
2127 /* TCP input state */
2128 return link
->data
.tcp
->state
.in
;
2133 GetStateOut(struct alias_link
*link
)
2135 /* TCP output state */
2136 return link
->data
.tcp
->state
.out
;
2141 GetOriginalAddress(struct alias_link
*link
)
2143 if (link
->src_addr
.s_addr
== INADDR_ANY
)
2144 return aliasAddress
;
2146 return(link
->src_addr
);
2151 GetDestAddress(struct alias_link
*link
)
2153 return(link
->dst_addr
);
2158 GetAliasAddress(struct alias_link
*link
)
2160 if (link
->alias_addr
.s_addr
== INADDR_ANY
)
2161 return aliasAddress
;
2163 return link
->alias_addr
;
2168 GetDefaultAliasAddress()
2170 return aliasAddress
;
2175 SetDefaultAliasAddress(struct in_addr alias_addr
)
2177 aliasAddress
= alias_addr
;
2182 GetOriginalPort(struct alias_link
*link
)
2184 return(link
->src_port
);
2189 GetAliasPort(struct alias_link
*link
)
2191 return(link
->alias_port
);
2196 GetDestPort(struct alias_link
*link
)
2198 return(link
->dst_port
);
2203 SetAckModified(struct alias_link
*link
)
2205 /* Indicate that ACK numbers have been modified in a TCP connection */
2206 link
->data
.tcp
->state
.ack_modified
= 1;
2211 GetProxyAddress(struct alias_link
*link
)
2213 return link
->proxy_addr
;
2218 SetProxyAddress(struct alias_link
*link
, struct in_addr addr
)
2220 link
->proxy_addr
= addr
;
2225 GetProxyPort(struct alias_link
*link
)
2227 return link
->proxy_port
;
2232 SetProxyPort(struct alias_link
*link
, u_short port
)
2234 link
->proxy_port
= port
;
2239 GetAckModified(struct alias_link
*link
)
2241 /* See if ACK numbers have been modified */
2242 return link
->data
.tcp
->state
.ack_modified
;
2247 GetDeltaAckIn(struct ip
*pip
, struct alias_link
*link
)
2250 Find out how much the ACK number has been altered for an incoming
2251 TCP packet. To do this, a circular list of ACK numbers where the TCP
2252 packet size was altered is searched.
2257 int delta
, ack_diff_min
;
2260 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2265 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
2267 struct ack_data_record x
;
2269 x
= link
->data
.tcp
->ack
[i
];
2274 ack_diff
= SeqDiff(x
.ack_new
, ack
);
2277 if (ack_diff_min
>= 0)
2279 if (ack_diff
< ack_diff_min
)
2282 ack_diff_min
= ack_diff
;
2288 ack_diff_min
= ack_diff
;
2298 GetDeltaSeqOut(struct ip
*pip
, struct alias_link
*link
)
2301 Find out how much the sequence number has been altered for an outgoing
2302 TCP packet. To do this, a circular list of ACK numbers where the TCP
2303 packet size was altered is searched.
2308 int delta
, seq_diff_min
;
2311 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2316 for (i
=0; i
<N_LINK_TCP_DATA
; i
++)
2318 struct ack_data_record x
;
2320 x
= link
->data
.tcp
->ack
[i
];
2325 seq_diff
= SeqDiff(x
.ack_old
, seq
);
2328 if (seq_diff_min
>= 0)
2330 if (seq_diff
< seq_diff_min
)
2333 seq_diff_min
= seq_diff
;
2339 seq_diff_min
= seq_diff
;
2349 AddSeq(struct ip
*pip
, struct alias_link
*link
, int delta
)
2352 When a TCP packet has been altered in length, save this
2353 information in a circular list. If enough packets have
2354 been altered, then this list will begin to overwrite itself.
2358 struct ack_data_record x
;
2359 int hlen
, tlen
, dlen
;
2362 tc
= (struct tcphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
2364 hlen
= (pip
->ip_hl
+ tc
->th_off
) << 2;
2365 tlen
= ntohs(pip
->ip_len
);
2368 x
.ack_old
= htonl(ntohl(tc
->th_seq
) + dlen
);
2369 x
.ack_new
= htonl(ntohl(tc
->th_seq
) + dlen
+ delta
);
2373 i
= link
->data
.tcp
->state
.index
;
2374 link
->data
.tcp
->ack
[i
] = x
;
2377 if (i
== N_LINK_TCP_DATA
)
2378 link
->data
.tcp
->state
.index
= 0;
2380 link
->data
.tcp
->state
.index
= i
;
2384 SetExpire(struct alias_link
*link
, int expire
)
2388 link
->flags
&= ~LINK_PERMANENT
;
2391 else if (expire
== -1)
2393 link
->flags
|= LINK_PERMANENT
;
2395 else if (expire
> 0)
2397 link
->expire_time
= expire
;
2402 fprintf(stderr
, "PacketAlias/SetExpire(): ");
2403 fprintf(stderr
, "error in expire parameter\n");
2409 ClearCheckNewLink(void)
2415 SetLastLineCrlfTermed(struct alias_link
*link
, int yes
)
2419 link
->flags
|= LINK_LAST_LINE_CRLF_TERMED
;
2421 link
->flags
&= ~LINK_LAST_LINE_CRLF_TERMED
;
2425 GetLastLineCrlfTermed(struct alias_link
*link
)
2428 return (link
->flags
& LINK_LAST_LINE_CRLF_TERMED
);
2432 SetDestCallId(struct alias_link
*link
, u_int16_t cid
)
2436 link
= ReLink(link
, link
->src_addr
, link
->dst_addr
, link
->alias_addr
,
2437 link
->src_port
, cid
, link
->alias_port
, link
->link_type
);
2442 /* Miscellaneous Functions
2445 InitPacketAliasLog()
2446 UninitPacketAliasLog()
2450 Whenever an outgoing or incoming packet is handled, HouseKeeping()
2451 is called to find and remove timed-out aliasing links. Logic exists
2452 to sweep through the entire table and linked list structure
2455 (prototype in alias_local.h)
2466 * Save system time (seconds) in global variable timeStamp for
2467 * use by other functions. This is done so as not to unnecessarily
2468 * waste timeline by making system calls.
2470 gettimeofday(&tv
, &tz
);
2471 timeStamp
= tv
.tv_sec
;
2473 /* Compute number of spokes (output table link chains) to cover */
2474 n100
= LINK_TABLE_OUT_SIZE
* 100 + houseKeepingResidual
;
2475 n100
*= timeStamp
- lastCleanupTime
;
2476 n100
/= ALIAS_CLEANUP_INTERVAL_SECS
;
2480 /* Handle different cases */
2481 if (n
> ALIAS_CLEANUP_MAX_SPOKES
)
2483 n
= ALIAS_CLEANUP_MAX_SPOKES
;
2484 lastCleanupTime
= timeStamp
;
2485 houseKeepingResidual
= 0;
2488 IncrementalCleanup();
2492 lastCleanupTime
= timeStamp
;
2493 houseKeepingResidual
= n100
- 100*n
;
2496 IncrementalCleanup();
2501 fprintf(stderr
, "PacketAlias/HouseKeeping(): ");
2502 fprintf(stderr
, "something unexpected in time values\n");
2504 lastCleanupTime
= timeStamp
;
2505 houseKeepingResidual
= 0;
2510 /* Init the log file and enable logging */
2512 InitPacketAliasLog(void)
2514 if ((~packetAliasMode
& PKT_ALIAS_LOG
)
2515 && (monitorFile
= fopen("/var/log/alias.log", "w")))
2517 packetAliasMode
|= PKT_ALIAS_LOG
;
2518 fprintf(monitorFile
,
2519 "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
2524 /* Close the log-file and disable logging. */
2526 UninitPacketAliasLog(void)
2529 fclose(monitorFile
);
2532 packetAliasMode
&= ~PKT_ALIAS_LOG
;
2540 /* Outside world interfaces
2542 -- "outside world" means other than alias*.c routines --
2544 PacketAliasRedirectPort()
2545 PacketAliasAddServer()
2546 PacketAliasRedirectProto()
2547 PacketAliasRedirectAddr()
2548 PacketAliasRedirectDelete()
2549 PacketAliasSetAddress()
2552 PacketAliasSetMode()
2554 (prototypes in alias.h)
2557 /* Redirection from a specific public addr:port to a
2558 private addr:port */
2560 PacketAliasRedirectPort(struct in_addr src_addr
, u_short src_port
,
2561 struct in_addr dst_addr
, u_short dst_port
,
2562 struct in_addr alias_addr
, u_short alias_port
,
2566 struct alias_link
*link
;
2571 link_type
= LINK_UDP
;
2574 link_type
= LINK_TCP
;
2578 fprintf(stderr
, "PacketAliasRedirectPort(): ");
2579 fprintf(stderr
, "only TCP and UDP protocols allowed\n");
2584 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2585 src_port
, dst_port
, alias_port
,
2590 link
->flags
|= LINK_PERMANENT
;
2595 fprintf(stderr
, "PacketAliasRedirectPort(): "
2596 "call to AddLink() failed\n");
2603 /* Add server to the pool of servers */
2605 PacketAliasAddServer(struct alias_link
*link
, struct in_addr addr
, u_short port
)
2607 struct server
*server
;
2609 server
= malloc(sizeof(struct server
));
2611 if (server
!= NULL
) {
2612 struct server
*head
;
2614 server
->addr
= addr
;
2615 server
->port
= port
;
2617 head
= link
->server
;
2619 server
->next
= server
;
2623 for (s
= head
; s
->next
!= head
; s
= s
->next
);
2625 server
->next
= head
;
2627 link
->server
= server
;
2633 /* Redirect packets of a given IP protocol from a specific
2634 public address to a private address */
2636 PacketAliasRedirectProto(struct in_addr src_addr
,
2637 struct in_addr dst_addr
,
2638 struct in_addr alias_addr
,
2641 struct alias_link
*link
;
2643 link
= AddLink(src_addr
, dst_addr
, alias_addr
,
2644 NO_SRC_PORT
, NO_DEST_PORT
, 0,
2649 link
->flags
|= LINK_PERMANENT
;
2654 fprintf(stderr
, "PacketAliasRedirectProto(): "
2655 "call to AddLink() failed\n");
2662 /* Static address translation */
2664 PacketAliasRedirectAddr(struct in_addr src_addr
,
2665 struct in_addr alias_addr
)
2667 struct alias_link
*link
;
2669 link
= AddLink(src_addr
, nullAddress
, alias_addr
,
2675 link
->flags
|= LINK_PERMANENT
;
2680 fprintf(stderr
, "PacketAliasRedirectAddr(): "
2681 "call to AddLink() failed\n");
2690 PacketAliasRedirectDelete(struct alias_link
*link
)
2692 /* This is a dangerous function to put in the API,
2693 because an invalid pointer can crash the program. */
2702 PacketAliasSetAddress(struct in_addr addr
)
2704 if (packetAliasMode
& PKT_ALIAS_RESET_ON_ADDR_CHANGE
2705 && aliasAddress
.s_addr
!= addr
.s_addr
)
2708 aliasAddress
= addr
;
2713 PacketAliasSetTarget(struct in_addr target_addr
)
2715 targetAddress
= target_addr
;
2720 PacketAliasInit(void)
2725 static int firstCall
= 1;
2729 gettimeofday(&tv
, &tz
);
2730 timeStamp
= tv
.tv_sec
;
2731 lastCleanupTime
= tv
.tv_sec
;
2732 houseKeepingResidual
= 0;
2734 for (i
=0; i
<LINK_TABLE_OUT_SIZE
; i
++)
2735 LIST_INIT(&linkTableOut
[i
]);
2736 for (i
=0; i
<LINK_TABLE_IN_SIZE
; i
++)
2737 LIST_INIT(&linkTableIn
[i
]);
2739 atexit(PacketAliasUninit
);
2749 aliasAddress
.s_addr
= INADDR_ANY
;
2750 targetAddress
.s_addr
= INADDR_ANY
;
2757 fragmentIdLinkCount
= 0;
2758 fragmentPtrLinkCount
= 0;
2763 packetAliasMode
= PKT_ALIAS_SAME_PORTS
2764 | PKT_ALIAS_USE_SOCKETS
2765 | PKT_ALIAS_RESET_ON_ADDR_CHANGE
;
2769 PacketAliasUninit(void) {
2773 UninitPacketAliasLog();
2780 /* Change mode for some operations */
2783 unsigned int flags
, /* Which state to bring flags to */
2784 unsigned int mask
/* Mask of which flags to affect (use 0 to do a
2785 probe for flag values) */
2788 /* Enable logging? */
2789 if (flags
& mask
& PKT_ALIAS_LOG
)
2791 InitPacketAliasLog(); /* Do the enable */
2793 /* _Disable_ logging? */
2794 if (~flags
& mask
& PKT_ALIAS_LOG
) {
2795 UninitPacketAliasLog();
2799 /* Start punching holes in the firewall? */
2800 if (flags
& mask
& PKT_ALIAS_PUNCH_FW
) {
2803 /* Stop punching holes in the firewall? */
2804 if (~flags
& mask
& PKT_ALIAS_PUNCH_FW
) {
2809 /* Other flags can be set/cleared without special action */
2810 packetAliasMode
= (flags
& mask
) | (packetAliasMode
& ~mask
);
2811 return packetAliasMode
;
2816 PacketAliasCheckNewLink(void)
2818 return newDefaultLink
;
2825 Code to support firewall punching. This shouldn't really be in this
2826 file, but making variables global is evil too.
2829 /* Firewall include files */
2831 #include <netinet/ip_fw.h>
2835 static void ClearAllFWHoles(void);
2837 static int fireWallBaseNum
; /* The first firewall entry free for our use */
2838 static int fireWallNumNums
; /* How many entries can we use? */
2839 static int fireWallActiveNum
; /* Which entry did we last use? */
2840 static char *fireWallField
; /* bool array for entries */
2842 #define fw_setfield(field, num) \
2844 (field)[(num) - fireWallBaseNum] = 1; \
2845 } /*lint -save -e717 */ while(0) /*lint -restore */
2846 #define fw_clrfield(field, num) \
2848 (field)[(num) - fireWallBaseNum] = 0; \
2849 } /*lint -save -e717 */ while(0) /*lint -restore */
2850 #define fw_tstfield(field, num) ((field)[(num) - fireWallBaseNum])
2854 fireWallField
= malloc(fireWallNumNums
);
2855 if (fireWallField
) {
2856 memset(fireWallField
, 0, fireWallNumNums
);
2857 if (fireWallFD
< 0) {
2858 fireWallFD
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
2861 fireWallActiveNum
= fireWallBaseNum
;
2866 UninitPunchFW(void) {
2868 if (fireWallFD
>= 0)
2872 free(fireWallField
);
2873 fireWallField
= NULL
;
2874 packetAliasMode
&= ~PKT_ALIAS_PUNCH_FW
;
2877 /* Make a certain link go through the firewall */
2879 PunchFWHole(struct alias_link
*link
) {
2880 int r
; /* Result code */
2881 struct ip_fw rule
; /* On-the-fly built rule */
2882 int fwhole
; /* Where to punch hole */
2884 /* Don't do anything unless we are asked to */
2885 if ( !(packetAliasMode
& PKT_ALIAS_PUNCH_FW
) ||
2887 link
->link_type
!= LINK_TCP
)
2890 memset(&rule
, 0, sizeof rule
);
2894 /* Find empty slot */
2895 for (fwhole
= fireWallActiveNum
;
2896 fwhole
< fireWallBaseNum
+ fireWallNumNums
&&
2897 fw_tstfield(fireWallField
, fwhole
);
2900 if (fwhole
== fireWallBaseNum
+ fireWallNumNums
) {
2901 for (fwhole
= fireWallBaseNum
;
2902 fwhole
< fireWallActiveNum
&&
2903 fw_tstfield(fireWallField
, fwhole
);
2906 if (fwhole
== fireWallActiveNum
) {
2907 /* No rule point empty - we can't punch more holes. */
2908 fireWallActiveNum
= fireWallBaseNum
;
2910 fprintf(stderr
, "libalias: Unable to create firewall hole!\n");
2915 /* Start next search at next position */
2916 fireWallActiveNum
= fwhole
+1;
2918 /* Build generic part of the two rules */
2919 rule
.fw_number
= fwhole
;
2920 IP_FW_SETNSRCP(&rule
, 1); /* Number of source ports. */
2921 IP_FW_SETNDSTP(&rule
, 1); /* Number of destination ports. */
2922 rule
.fw_flg
= IP_FW_F_ACCEPT
| IP_FW_F_IN
| IP_FW_F_OUT
;
2923 rule
.fw_prot
= IPPROTO_TCP
;
2924 rule
.fw_smsk
.s_addr
= INADDR_BROADCAST
;
2925 rule
.fw_dmsk
.s_addr
= INADDR_BROADCAST
;
2927 /* Build and apply specific part of the rules */
2928 rule
.fw_src
= GetOriginalAddress(link
);
2929 rule
.fw_dst
= GetDestAddress(link
);
2930 rule
.fw_uar
.fw_pts
[0] = ntohs(GetOriginalPort(link
));
2931 rule
.fw_uar
.fw_pts
[1] = ntohs(GetDestPort(link
));
2933 /* Skip non-bound links - XXX should not be strictly necessary,
2934 but seems to leave hole if not done. Leak of non-bound links?
2935 (Code should be left even if the problem is fixed - it is a
2936 clear optimization) */
2937 if (rule
.fw_uar
.fw_pts
[0] != 0 && rule
.fw_uar
.fw_pts
[1] != 0) {
2938 r
= setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_ADD
, &rule
, sizeof rule
);
2941 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2943 rule
.fw_src
= GetDestAddress(link
);
2944 rule
.fw_dst
= GetOriginalAddress(link
);
2945 rule
.fw_uar
.fw_pts
[0] = ntohs(GetDestPort(link
));
2946 rule
.fw_uar
.fw_pts
[1] = ntohs(GetOriginalPort(link
));
2947 r
= setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_ADD
, &rule
, sizeof rule
);
2950 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2953 /* Indicate hole applied */
2954 link
->data
.tcp
->fwhole
= fwhole
;
2955 fw_setfield(fireWallField
, fwhole
);
2958 /* Remove a hole in a firewall associated with a particular alias
2959 link. Calling this too often is harmless. */
2961 ClearFWHole(struct alias_link
*link
) {
2962 if (link
->link_type
== LINK_TCP
) {
2963 int fwhole
= link
->data
.tcp
->fwhole
; /* Where is the firewall hole? */
2969 memset(&rule
, 0, sizeof rule
);
2970 rule
.fw_number
= fwhole
;
2971 while (!setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_DEL
, &rule
, sizeof rule
))
2973 fw_clrfield(fireWallField
, fwhole
);
2974 link
->data
.tcp
->fwhole
= -1;
2978 /* Clear out the entire range dedicated to firewall holes. */
2980 ClearAllFWHoles(void) {
2981 struct ip_fw rule
; /* On-the-fly built rule */
2987 memset(&rule
, 0, sizeof rule
);
2988 for (i
= fireWallBaseNum
; i
< fireWallBaseNum
+ fireWallNumNums
; i
++) {
2990 while (!setsockopt(fireWallFD
, IPPROTO_IP
, IP_FW_DEL
, &rule
, sizeof rule
))
2993 memset(fireWallField
, 0, fireWallNumNums
);
2998 PacketAliasSetFWBase(unsigned int base
, unsigned int num
) {
3000 fireWallBaseNum
= base
;
3001 fireWallNumNums
= num
;