1 /* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*-
2 Alias_db.c encapsulates all data structures used for storing
3 packet aliasing data. Other parts of the aliasing software
4 access data through functions provided in this file.
6 Data storage is based on the notion of a "link", which is
7 established for ICMP echo/reply packets, UDP datagrams and
8 TCP stream connections. A link stores the original source
9 and destination addresses. For UDP and TCP, it also stores
10 source and destination port numbers, as well as an alias
11 port number. Links are also used to store information about
14 There is a facility for sweeping through and deleting old
15 links as new packets are sent through. A simple timeout is
16 used for ICMP and UDP links. TCP links are left alone unless
17 there is an incomplete connection, in which case the link
18 can be deleted after a certain amount of time.
21 This software is placed into the public domain with no restrictions
24 Initial version: August, 1996 (cjm)
26 Version 1.4: September 16, 1996 (cjm)
27 Facility for handling incoming links added.
29 Version 1.6: September 18, 1996 (cjm)
30 ICMP data handling simplified.
32 Version 1.7: January 9, 1997 (cjm)
33 Fragment handling simplified.
34 Saves pointers for unresolved fragments.
35 Permits links for unspecied remote ports
36 or unspecified remote addresses.
37 Fixed bug which did not properly zero port
38 table entries after a link was deleted.
39 Cleaned up some obsolete comments.
41 Version 1.8: January 14, 1997 (cjm)
42 Fixed data type error in StartPoint().
43 (This error did not exist prior to v1.7
44 and was discovered and fixed by Ari Suutari)
46 Version 1.9: February 1, 1997
47 Optionally, connections initiated from packet aliasing host
48 machine will will not have their port number aliased unless it
49 conflicts with an aliasing port already being used. (cjm)
51 All options earlier being #ifdef'ed now are available through
52 a new interface, SetPacketAliasMode(). This allow run time
53 control (which is now available in PPP+pktAlias through the
54 'alias' keyword). (ee)
56 Added ability to create an alias port without
57 either destination address or port specified.
58 port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
60 Removed K&R style function headers
61 and general cleanup. (ee)
63 Added packetAliasMode to replace compiler #defines's (ee)
65 Allocates sockets for partially specified
66 ports if ALIAS_USE_SOCKETS defined. (cjm)
68 Version 2.0: March, 1997
69 SetAliasAddress() will now clean up alias links
70 if the aliasing address is changed. (cjm)
72 PacketAliasPermanentLink() function added to support permanent
73 links. (J. Fortes suggested the need for this.)
76 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port
78 (192.168.0.2, port 21) <-> alias port 3604, known dest addr
81 These permament links allow for incoming connections to
82 machines on the local network. They can be given with a
83 user-chosen amount of specificity, with increasing specificity
84 meaning more security. (cjm)
86 Quite a bit of rework to the basic engine. The portTable[]
87 array, which kept track of which ports were in use was replaced
88 by a table/linked list structure. (cjm)
90 SetExpire() function added. (cjm)
92 DeleteLink() no longer frees memory association with a pointer
93 to a fragment (this bug was first recognized by E. Eklund in
96 Version 2.1: May, 1997 (cjm)
97 Packet aliasing engine reworked so that it can handle
98 multiple external addresses rather than just a single
101 PacketAliasRedirectPort() and PacketAliasRedirectAddr()
102 added to the API. The first function is a more generalized
103 version of PacketAliasPermanentLink(). The second function
104 implements static network address translation.
106 See HISTORY file for additional revisions.
110 /* System include files */
115 #include <sys/errno.h>
116 #include <sys/socket.h>
117 #include <sys/time.h>
118 #include <sys/types.h>
120 /* BSD network include files */
121 #include <netinet/in_systm.h>
122 #include <netinet/in.h>
123 #include <netinet/ip.h>
124 #include <netinet/tcp.h>
125 #include <arpa/inet.h>
128 #include "alias_local.h"
133 Constants (note: constants are also defined
134 near relevant functions or structs)
137 /* Sizes of input and output link tables */
138 #define LINK_TABLE_OUT_SIZE 101
139 #define LINK_TABLE_IN_SIZE 4001
141 /* Parameters used for cleanup of expired links */
142 #define ALIAS_CLEANUP_INTERVAL_SECS 60
143 #define ALIAS_CLEANUP_MAX_SPOKES 30
145 /* Timouts (in seconds) for different link types) */
146 #define ICMP_EXPIRE_TIME 60
147 #define UDP_EXPIRE_TIME 60
148 #define FRAGMENT_ID_EXPIRE_TIME 10
149 #define FRAGMENT_PTR_EXPIRE_TIME 30
151 /* TCP link expire time for different cases */
152 /* When the link has been used and closed - minimal grace time to
153 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */
154 #ifndef TCP_EXPIRE_DEAD
155 # define TCP_EXPIRE_DEAD 10
158 /* When the link has been used and closed on one side - the other side
159 is allowed to still send data */
160 #ifndef TCP_EXPIRE_SINGLEDEAD
161 # define TCP_EXPIRE_SINGLEDEAD 90
164 /* When the link isn't yet up */
165 #ifndef TCP_EXPIRE_INITIAL
166 # define TCP_EXPIRE_INITIAL 300
169 /* When the link is up */
170 #ifndef TCP_EXPIRE_CONNECTED
171 # define TCP_EXPIRE_CONNECTED 86400
175 /* Dummy port number codes used for FindLinkIn/Out() and AddLink().
176 These constants can be anything except zero, which indicates an
177 unknown port number. */
179 #define NO_DEST_PORT 1
180 #define NO_SRC_PORT 1
186 The fundamental data structure used in this program is
187 "struct alias_link". Whenever a TCP connection is made,
188 a UDP datagram is sent out, or an ICMP echo request is made,
189 a link record is made (if it has not already been created).
190 The link record is identified by the source address/port
191 and the destination address/port. In the case of an ICMP
192 echo request, the source port is treated as being equivalent
193 with the 16-bit id number of the ICMP packet.
195 The link record also can store some auxiliary data. For
196 TCP connections that have had sequence and acknowledgment
197 modifications, data space is available to track these changes.
198 A state field is used to keep track in changes to the tcp
199 connection state. Id numbers of fragments can also be
200 stored in the auxiliary space. Pointers to unresolved
201 framgents can also be stored.
203 The link records support two independent chainings. Lookup
204 tables for input and out tables hold the initial pointers
205 the link chains. On input, the lookup table indexes on alias
206 port and link type. On output, the lookup table indexes on
207 source addreess, destination address, source port, destination
211 struct ack_data_record /* used to save changes to ack/seq numbers */
219 struct tcp_state /* Information about tcp connection */
221 int in; /* State for outside -> inside */
222 int out; /* State for inside -> outside */
223 int index; /* Index to ack data array */
224 int ack_modified; /* Indicates whether ack and seq numbers */
228 #define N_LINK_TCP_DATA 3 /* Number of distinct ack number changes
229 saved for a modified TCP stream */
232 struct tcp_state state;
233 struct ack_data_record ack[N_LINK_TCP_DATA];
234 int fwhole; /* Which firewall record is used for this hole? */
237 struct alias_link /* Main data structure */
239 struct in_addr src_addr; /* Address and port information */
240 struct in_addr dst_addr;
241 struct in_addr alias_addr;
242 struct in_addr proxy_addr;
248 int link_type; /* Type of link: tcp, udp, icmp, frag */
250 /* values for link_type */
254 #define LINK_FRAGMENT_ID 4
255 #define LINK_FRAGMENT_PTR 5
258 int flags; /* indicates special characteristics */
261 #define LINK_UNKNOWN_DEST_PORT 0x01
262 #define LINK_UNKNOWN_DEST_ADDR 0x02
263 #define LINK_PERMANENT 0x04
264 #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */
265 #define LINK_UNFIREWALLED 0x08
267 int timestamp; /* Time link was last accessed */
268 int expire_time; /* Expire time for link */
270 int sockfd; /* socket descriptor */
272 u_int start_point_out; /* Index number in output lookup table */
273 u_int start_point_in;
274 struct alias_link *next_out; /* Linked list pointers for input and */
275 struct alias_link *last_out; /* output tables */
276 struct alias_link *next_in; /* . */
277 struct alias_link *last_in; /* . */
279 union /* Auxiliary data */
282 struct in_addr frag_addr;
293 The global variables listed here are only accessed from
294 within alias_db.c and so are prefixed with the static
298 int packetAliasMode; /* Mode flags */
299 /* - documented in alias.h */
301 static struct in_addr aliasAddress; /* Address written onto source */
302 /* field of IP packet. */
304 static struct in_addr targetAddress; /* IP address incoming packets */
305 /* are sent to if no aliasing */
306 /* link already exists */
308 static struct in_addr nullAddress; /* Used as a dummy parameter for */
309 /* some function calls */
310 static struct alias_link *
311 linkTableOut[LINK_TABLE_OUT_SIZE]; /* Lookup table of pointers to */
312 /* chains of link records. Each */
313 static struct alias_link * /* link record is doubly indexed */
314 linkTableIn[LINK_TABLE_IN_SIZE]; /* into input and output lookup */
317 static int icmpLinkCount; /* Link statistics */
318 static int udpLinkCount;
319 static int tcpLinkCount;
320 static int fragmentIdLinkCount;
321 static int fragmentPtrLinkCount;
322 static int sockCount;
324 static int cleanupIndex; /* Index to chain of link table */
325 /* being inspected for old links */
327 static int timeStamp; /* System time in seconds for */
330 static int lastCleanupTime; /* Last time IncrementalCleanup() */
333 static int houseKeepingResidual; /* used by HouseKeeping() */
335 static int deleteAllLinks; /* If equal to zero, DeleteLink() */
336 /* will not remove permanent links */
338 static FILE *monitorFile; /* File descriptor for link */
339 /* statistics monitoring file */
341 static int newDefaultLink; /* Indicates if a new aliasing */
342 /* link has been created after a */
343 /* call to PacketAliasIn/Out(). */
346 static int fireWallFD = -1; /* File descriptor to be able to */
347 /* control firewall. Opened by */
348 /* PacketAliasSetMode on first */
349 /* setting the PKT_ALIAS_PUNCH_FW */
353 static int pptpAliasFlag; /* Indicates if PPTP aliasing is */
355 static struct in_addr pptpAliasAddr; /* Address of source of PPTP */
364 /* Internal utility routines (used only in alias_db.c)
366 Lookup table starting points:
367 StartPointIn() -- link table initial search point for
369 StartPointOut() -- port table initial search point for
373 SeqDiff() -- difference between two TCP sequences
374 ShowAliasStats() -- send alias statistics to a monitor file
378 /* Local prototypes */
379 static u_int StartPointIn(struct in_addr, u_short, int);
381 static u_int StartPointOut(struct in_addr, struct in_addr,
382 u_short, u_short, int);
384 static int SeqDiff(u_long, u_long);
386 static void ShowAliasStats(void);
389 /* Firewall control */
390 static void InitPunchFW(void);
391 static void UninitPunchFW(void);
392 static void ClearFWHole(struct alias_link *link);
395 /* Log file control */
396 static void InitPacketAliasLog(void);
397 static void UninitPacketAliasLog(void);
400 StartPointIn(struct in_addr alias_addr,
406 n = alias_addr.s_addr;
409 return(n % LINK_TABLE_IN_SIZE);
414 StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
415 u_short src_port, u_short dst_port, int link_type)
420 n += dst_addr.s_addr;
425 return(n % LINK_TABLE_OUT_SIZE);
430 SeqDiff(u_long x, u_long y)
432 /* Return the difference between two TCP sequence numbers */
435 This function is encapsulated in case there are any unusual
436 arithmetic conditions that need to be considered.
439 return (ntohl(y) - ntohl(x));
446 /* Used for debugging */
450 fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, frag_id=%d frag_ptr=%d",
455 fragmentPtrLinkCount);
457 fprintf(monitorFile, " / tot=%d (sock=%d)\n",
458 icmpLinkCount + udpLinkCount
460 + fragmentIdLinkCount
461 + fragmentPtrLinkCount,
472 /* Internal routines for finding, deleting and adding links
475 GetNewPort() -- find and reserve new alias port number
476 GetSocket() -- try to allocate a socket for a given port
478 Link creation and deletion:
479 CleanupAliasData() - remove all link chains from lookup table
480 IncrementalCleanup() - look for stale links in a single chain
481 DeleteLink() - remove link
483 ReLink() - change link
486 FindLinkOut() - find link for outgoing packets
487 FindLinkIn() - find link for incoming packets
490 /* Local prototypes */
491 static int GetNewPort(struct alias_link *, int);
493 static u_short GetSocket(u_short, int *, int);
495 static void CleanupAliasData(void);
497 static void IncrementalCleanup(void);
499 static void DeleteLink(struct alias_link *);
501 static struct alias_link *
502 AddLink(struct in_addr, struct in_addr, struct in_addr,
503 u_short, u_short, int, int);
505 static struct alias_link *
506 ReLink(struct alias_link *,
507 struct in_addr, struct in_addr, struct in_addr,
508 u_short, u_short, int, int);
510 static struct alias_link *
511 FindLinkOut(struct in_addr, struct in_addr, u_short, u_short, int);
513 static struct alias_link *
514 FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int);
517 #define ALIAS_PORT_BASE 0x08000
518 #define ALIAS_PORT_MASK 0x07fff
519 #define GET_NEW_PORT_MAX_ATTEMPTS 20
521 #define GET_ALIAS_PORT -1
522 #define GET_ALIAS_ID GET_ALIAS_PORT
524 /* GetNewPort() allocates port numbers. Note that if a port number
525 is already in use, that does not mean that it cannot be used by
526 another link concurrently. This is because GetNewPort() looks for
527 unused triplets: (dest addr, dest port, alias port). */
530 GetNewPort(struct alias_link *link, int alias_port_param)
538 Description of alias_port_param for GetNewPort(). When
539 this parameter is zero or positive, it precisely specifies
540 the port number. GetNewPort() will return this number
541 without check that it is in use.
543 Whis this parameter is -1, it indicates to get a randomly
544 selected port number.
547 if (alias_port_param == GET_ALIAS_PORT)
550 * The aliasing port is automatically selected
551 * by one of two methods below:
553 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
555 if (packetAliasMode & PKT_ALIAS_SAME_PORTS)
558 * When the ALIAS_SAME_PORTS option is
559 * chosen, the first try will be the
560 * actual source port. If this is already
561 * in use, the remainder of the trials
564 port_net = link->src_port;
565 port_sys = ntohs(port_net);
569 /* First trial and all subsequent are random. */
570 port_sys = random() & ALIAS_PORT_MASK;
571 port_sys += ALIAS_PORT_BASE;
572 port_net = htons(port_sys);
575 else if (alias_port_param >= 0 && alias_port_param < 0x10000)
577 link->alias_port = (u_short) alias_port_param;
582 fprintf(stderr, "PacketAlias/GetNewPort(): ");
583 fprintf(stderr, "input parameter error\n");
588 /* Port number search */
589 for (i=0; i<max_trials; i++)
592 struct alias_link *search_result;
594 search_result = FindLinkIn(link->dst_addr, link->alias_addr,
595 link->dst_port, port_net,
598 if (search_result == NULL)
600 else if (!(link->flags & LINK_PARTIALLY_SPECIFIED)
601 && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
608 if ((packetAliasMode && PKT_ALIAS_USE_SOCKETS)
609 && (link->flags & LINK_PARTIALLY_SPECIFIED))
611 if (GetSocket(port_net, &link->sockfd, link->link_type))
613 link->alias_port = port_net;
619 link->alias_port = port_net;
624 port_sys = random() & ALIAS_PORT_MASK;
625 port_sys += ALIAS_PORT_BASE;
626 port_net = htons(port_sys);
629 fprintf(stderr, "PacketAlias/GetnewPort(): ");
630 fprintf(stderr, "could not find free port\n");
637 GetSocket(u_short port_net, int *sockfd, int link_type)
641 struct sockaddr_in sock_addr;
643 if (link_type == LINK_TCP)
644 sock = socket(AF_INET, SOCK_STREAM, 0);
645 else if (link_type == LINK_UDP)
646 sock = socket(AF_INET, SOCK_DGRAM, 0);
649 fprintf(stderr, "PacketAlias/GetSocket(): ");
650 fprintf(stderr, "incorrect link type\n");
656 fprintf(stderr, "PacketAlias/GetSocket(): ");
657 fprintf(stderr, "socket() error %d\n", *sockfd);
661 sock_addr.sin_family = AF_INET;
662 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
663 sock_addr.sin_port = port_net;
666 (struct sockaddr *) &sock_addr,
683 CleanupAliasData(void)
685 struct alias_link *link;
689 for (i=0; i<LINK_TABLE_OUT_SIZE; i++)
691 link = linkTableOut[i];
694 struct alias_link *link_next;
695 link_next = link->next_out;
707 IncrementalCleanup(void)
710 struct alias_link *link;
713 link = linkTableOut[cleanupIndex++];
717 struct alias_link *link_next;
719 link_next = link->next_out;
720 idelta = timeStamp - link->timestamp;
721 switch (link->link_type)
725 case LINK_FRAGMENT_ID:
726 case LINK_FRAGMENT_PTR:
727 if (idelta > link->expire_time)
734 if (idelta > link->expire_time)
736 struct tcp_dat *tcp_aux;
738 tcp_aux = link->data.tcp;
739 if (tcp_aux->state.in != ALIAS_TCP_STATE_CONNECTED
740 || tcp_aux->state.out != ALIAS_TCP_STATE_CONNECTED)
751 if (cleanupIndex == LINK_TABLE_OUT_SIZE)
756 DeleteLink(struct alias_link *link)
758 struct alias_link *link_last;
759 struct alias_link *link_next;
761 /* Don't do anything if the link is marked permanent */
762 if (deleteAllLinks == 0 && link->flags & LINK_PERMANENT)
766 /* Delete associatied firewall hole, if any */
770 /* Adjust output table pointers */
771 link_last = link->last_out;
772 link_next = link->next_out;
774 if (link_last != NULL)
775 link_last->next_out = link_next;
777 linkTableOut[link->start_point_out] = link_next;
779 if (link_next != NULL)
780 link_next->last_out = link_last;
782 /* Adjust input table pointers */
783 link_last = link->last_in;
784 link_next = link->next_in;
786 if (link_last != NULL)
787 link_last->next_in = link_next;
789 linkTableIn[link->start_point_in] = link_next;
791 if (link_next != NULL)
792 link_next->last_in = link_last;
794 /* Close socket, if one has been allocated */
795 if (link->sockfd != -1)
801 /* Link-type dependent cleanup */
802 switch(link->link_type)
812 if (link->data.tcp != NULL)
813 free(link->data.tcp);
815 case LINK_FRAGMENT_ID:
816 fragmentIdLinkCount--;
818 case LINK_FRAGMENT_PTR:
819 fragmentPtrLinkCount--;
820 if (link->data.frag_ptr != NULL)
821 free(link->data.frag_ptr);
828 /* Write statistics, if logging enabled */
829 if (packetAliasMode & PKT_ALIAS_LOG)
836 static struct alias_link *
837 AddLink(struct in_addr src_addr,
838 struct in_addr dst_addr,
839 struct in_addr alias_addr,
842 int alias_port_param, /* if less than zero, alias */
843 int link_type) /* port will be automatically */
844 { /* chosen. If greater than */
845 u_int start_point; /* zero, equal to alias port */
846 struct alias_link *link;
847 struct alias_link *first_link;
849 link = malloc(sizeof(struct alias_link));
852 /* If either the aliasing address or source address are
853 equal to the default device address (equal to the
854 global variable aliasAddress), then set the alias
855 address field of the link record to zero */
857 if (src_addr.s_addr == aliasAddress.s_addr)
860 if (alias_addr.s_addr == aliasAddress.s_addr)
861 alias_addr.s_addr = 0;
863 /* Basic initialization */
864 link->src_addr = src_addr;
865 link->dst_addr = dst_addr;
866 link->alias_addr = alias_addr;
867 link->proxy_addr.s_addr = 0;
868 link->src_port = src_port;
869 link->dst_port = dst_port;
870 link->proxy_port = 0;
871 link->link_type = link_type;
874 link->timestamp = timeStamp;
876 /* Expiration time */
880 link->expire_time = ICMP_EXPIRE_TIME;
883 link->expire_time = UDP_EXPIRE_TIME;
886 link->expire_time = TCP_EXPIRE_INITIAL;
888 case LINK_FRAGMENT_ID:
889 link->expire_time = FRAGMENT_ID_EXPIRE_TIME;
891 case LINK_FRAGMENT_PTR:
892 link->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
896 /* Determine alias flags */
897 if (dst_addr.s_addr == 0)
898 link->flags |= LINK_UNKNOWN_DEST_ADDR;
900 link->flags |= LINK_UNKNOWN_DEST_PORT;
902 /* Determine alias port */
903 if (GetNewPort(link, alias_port_param) != 0)
909 /* Set up pointers for output lookup table */
910 start_point = StartPointOut(src_addr, dst_addr,
911 src_port, dst_port, link_type);
912 first_link = linkTableOut[start_point];
914 link->last_out = NULL;
915 link->next_out = first_link;
916 link->start_point_out = start_point;
918 if (first_link != NULL)
919 first_link->last_out = link;
921 linkTableOut[start_point] = link;
923 /* Set up pointers for input lookup table */
924 start_point = StartPointIn(alias_addr, link->alias_port, link_type);
925 first_link = linkTableIn[start_point];
927 link->last_in = NULL;
928 link->next_in = first_link;
929 link->start_point_in = start_point;
931 if (first_link != NULL)
932 first_link->last_in = link;
934 linkTableIn[start_point] = link;
936 /* Link-type dependent initialization */
939 struct tcp_dat *aux_tcp;
948 aux_tcp = malloc(sizeof(struct tcp_dat));
949 link->data.tcp = aux_tcp;
955 aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
956 aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
957 aux_tcp->state.index = 0;
958 aux_tcp->state.ack_modified = 0;
959 for (i=0; i<N_LINK_TCP_DATA; i++)
960 aux_tcp->ack[i].active = 0;
961 aux_tcp->fwhole = -1;
965 fprintf(stderr, "PacketAlias/AddLink: ");
966 fprintf(stderr, " cannot allocate auxiliary TCP data\n");
969 case LINK_FRAGMENT_ID:
970 fragmentIdLinkCount++;
972 case LINK_FRAGMENT_PTR:
973 fragmentPtrLinkCount++;
979 fprintf(stderr, "PacketAlias/AddLink(): ");
980 fprintf(stderr, "malloc() call failed.\n");
983 if (packetAliasMode & PKT_ALIAS_LOG)
991 static struct alias_link *
992 ReLink(struct alias_link *old_link,
993 struct in_addr src_addr,
994 struct in_addr dst_addr,
995 struct in_addr alias_addr,
998 int alias_port_param, /* if less than zero, alias */
999 int link_type) /* port will be automatically */
1000 { /* chosen. If greater than */
1001 struct alias_link *new_link; /* zero, equal to alias port */
1003 new_link = AddLink(src_addr, dst_addr, alias_addr,
1004 src_port, dst_port, alias_port_param,
1007 if (new_link != NULL &&
1008 old_link->link_type == LINK_TCP &&
1009 old_link->data.tcp &&
1010 old_link->data.tcp->fwhole > 0) {
1011 PunchFWHole(new_link);
1014 DeleteLink(old_link);
1018 static struct alias_link *
1019 FindLinkOut(struct in_addr src_addr,
1020 struct in_addr dst_addr,
1026 struct alias_link *link;
1028 if (src_addr.s_addr == aliasAddress.s_addr)
1029 src_addr.s_addr = 0;
1031 i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
1032 link = linkTableOut[i];
1033 while (link != NULL)
1035 if (link->src_addr.s_addr == src_addr.s_addr
1036 && link->dst_addr.s_addr == dst_addr.s_addr
1037 && link->dst_port == dst_port
1038 && link->src_port == src_port
1039 && link->link_type == link_type)
1041 link->timestamp = timeStamp;
1044 link = link->next_out;
1052 FindLinkIn(struct in_addr dst_addr,
1053 struct in_addr alias_addr,
1057 int replace_partial_links)
1061 struct alias_link *link;
1062 struct alias_link *link_fully_specified;
1063 struct alias_link *link_unknown_all;
1064 struct alias_link *link_unknown_dst_addr;
1065 struct alias_link *link_unknown_dst_port;
1067 /* Initialize pointers */
1068 link_fully_specified = NULL;
1069 link_unknown_all = NULL;
1070 link_unknown_dst_addr = NULL;
1071 link_unknown_dst_port = NULL;
1073 /* If either the dest addr or port is unknown, the search
1074 loop will have to know about this. */
1077 if (dst_addr.s_addr == 0)
1078 flags_in |= LINK_UNKNOWN_DEST_ADDR;
1080 flags_in |= LINK_UNKNOWN_DEST_PORT;
1082 /* The following allows permanent links to be
1083 be specified as using the default aliasing address
1084 (i.e. device interface address) without knowing
1085 in advance what that address is. */
1087 if (alias_addr.s_addr == aliasAddress.s_addr)
1088 alias_addr.s_addr = 0;
1091 start_point = StartPointIn(alias_addr, alias_port, link_type);
1092 link = linkTableIn[start_point];
1093 while (link != NULL)
1097 flags = flags_in | link->flags;
1098 if (!(flags & LINK_PARTIALLY_SPECIFIED))
1100 if (link->alias_addr.s_addr == alias_addr.s_addr
1101 && link->alias_port == alias_port
1102 && link->dst_addr.s_addr == dst_addr.s_addr
1103 && link->dst_port == dst_port
1104 && link->link_type == link_type)
1106 link_fully_specified = link;
1110 else if ((flags & LINK_UNKNOWN_DEST_ADDR)
1111 && (flags & LINK_UNKNOWN_DEST_PORT))
1113 if (link->alias_addr.s_addr == alias_addr.s_addr
1114 && link->alias_port == alias_port
1115 && link->link_type == link_type)
1117 if (link_unknown_all == NULL)
1118 link_unknown_all = link;
1121 else if (flags & LINK_UNKNOWN_DEST_ADDR)
1123 if (link->alias_addr.s_addr == alias_addr.s_addr
1124 && link->alias_port == alias_port
1125 && link->link_type == link_type
1126 && link->dst_port == dst_port)
1128 if (link_unknown_dst_addr == NULL)
1129 link_unknown_dst_addr = link;
1132 else if (flags & LINK_UNKNOWN_DEST_PORT)
1134 if (link->alias_addr.s_addr == alias_addr.s_addr
1135 && link->alias_port == alias_port
1136 && link->link_type == link_type
1137 && link->dst_addr.s_addr == dst_addr.s_addr)
1139 if (link_unknown_dst_port == NULL)
1140 link_unknown_dst_port = link;
1143 link = link->next_in;
1148 if (link_fully_specified != NULL)
1150 return link_fully_specified;
1152 else if (link_unknown_dst_port != NULL)
1154 return replace_partial_links
1155 ? ReLink(link_unknown_dst_port,
1156 link_unknown_dst_port->src_addr, dst_addr, alias_addr,
1157 link_unknown_dst_port->src_port, dst_port, alias_port,
1159 : link_unknown_dst_port;
1161 else if (link_unknown_dst_addr != NULL)
1163 return replace_partial_links
1164 ? ReLink(link_unknown_dst_addr,
1165 link_unknown_dst_addr->src_addr, dst_addr, alias_addr,
1166 link_unknown_dst_addr->src_port, dst_port, alias_port,
1168 : link_unknown_dst_addr;
1170 else if (link_unknown_all != NULL)
1172 return replace_partial_links
1173 ? ReLink(link_unknown_all,
1174 link_unknown_all->src_addr, dst_addr, alias_addr,
1175 link_unknown_all->src_port, dst_port, alias_port,
1188 /* External routines for finding/adding links
1190 -- "external" means outside alias_db.c, but within alias*.c --
1192 FindIcmpIn(), FindIcmpOut()
1193 FindFragmentIn1(), FindFragmentIn2()
1194 AddFragmentPtrLink(), FindFragmentPtr()
1195 FindUdpTcpIn(), FindUdpTcpOut()
1196 FindOriginalAddress(), FindAliasAddress()
1198 (prototypes in alias_local.h)
1203 FindIcmpIn(struct in_addr dst_addr,
1204 struct in_addr alias_addr,
1207 return FindLinkIn(dst_addr, alias_addr,
1208 NO_DEST_PORT, id_alias,
1214 FindIcmpOut(struct in_addr src_addr,
1215 struct in_addr dst_addr,
1218 struct alias_link * link;
1220 link = FindLinkOut(src_addr, dst_addr,
1225 struct in_addr alias_addr;
1227 alias_addr = FindAliasAddress(src_addr);
1228 link = AddLink(src_addr, dst_addr, alias_addr,
1229 id, NO_DEST_PORT, GET_ALIAS_ID,
1238 FindFragmentIn1(struct in_addr dst_addr,
1239 struct in_addr alias_addr,
1242 struct alias_link *link;
1244 link = FindLinkIn(dst_addr, alias_addr,
1245 NO_DEST_PORT, ip_id,
1246 LINK_FRAGMENT_ID, 0);
1250 link = AddLink(nullAddress, dst_addr, alias_addr,
1251 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1260 FindFragmentIn2(struct in_addr dst_addr, /* Doesn't add a link if one */
1261 struct in_addr alias_addr, /* is not found. */
1264 return FindLinkIn(dst_addr, alias_addr,
1265 NO_DEST_PORT, ip_id,
1266 LINK_FRAGMENT_ID, 0);
1271 AddFragmentPtrLink(struct in_addr dst_addr,
1274 return AddLink(nullAddress, dst_addr, nullAddress,
1275 NO_SRC_PORT, NO_DEST_PORT, ip_id,
1281 FindFragmentPtr(struct in_addr dst_addr,
1284 return FindLinkIn(dst_addr, nullAddress,
1285 NO_DEST_PORT, ip_id,
1286 LINK_FRAGMENT_PTR, 0);
1291 FindUdpTcpIn(struct in_addr dst_addr,
1292 struct in_addr alias_addr,
1298 struct alias_link *link;
1303 link_type = LINK_UDP;
1306 link_type = LINK_TCP;
1313 link = FindLinkIn(dst_addr, alias_addr,
1314 dst_port, alias_port,
1317 if (!(packetAliasMode & PKT_ALIAS_DENY_INCOMING)
1318 && !(packetAliasMode & PKT_ALIAS_PROXY_ONLY)
1321 struct in_addr target_addr;
1323 target_addr = FindOriginalAddress(alias_addr);
1324 link = AddLink(target_addr, dst_addr, alias_addr,
1325 alias_port, dst_port, alias_port,
1334 FindUdpTcpOut(struct in_addr src_addr,
1335 struct in_addr dst_addr,
1341 struct alias_link *link;
1346 link_type = LINK_UDP;
1349 link_type = LINK_TCP;
1356 link = FindLinkOut(src_addr, dst_addr, src_port, dst_port, link_type);
1360 struct in_addr alias_addr;
1362 alias_addr = FindAliasAddress(src_addr);
1363 link = AddLink(src_addr, dst_addr, alias_addr,
1364 src_port, dst_port, GET_ALIAS_PORT,
1373 FindOriginalAddress(struct in_addr alias_addr)
1375 struct alias_link *link;
1377 link = FindLinkIn(nullAddress, alias_addr,
1378 0, 0, LINK_ADDR, 0);
1382 if (targetAddress.s_addr != 0)
1383 return targetAddress;
1389 if (link->src_addr.s_addr == 0)
1390 return aliasAddress;
1392 return link->src_addr;
1398 FindAliasAddress(struct in_addr original_addr)
1400 struct alias_link *link;
1402 link = FindLinkOut(original_addr, nullAddress,
1406 return aliasAddress;
1410 if (link->alias_addr.s_addr == 0)
1411 return aliasAddress;
1413 return link->alias_addr;
1418 /* External routines for getting or changing link data
1419 (external to alias_db.c, but internal to alias*.c)
1421 SetFragmentData(), GetFragmentData()
1422 SetFragmentPtr(), GetFragmentPtr()
1423 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1424 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1425 GetOriginalPort(), GetAliasPort()
1426 SetAckModified(), GetAckModified()
1427 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1432 SetFragmentAddr(struct alias_link *link, struct in_addr src_addr)
1434 link->data.frag_addr = src_addr;
1439 GetFragmentAddr(struct alias_link *link, struct in_addr *src_addr)
1441 *src_addr = link->data.frag_addr;
1446 SetFragmentPtr(struct alias_link *link, char *fptr)
1448 link->data.frag_ptr = fptr;
1453 GetFragmentPtr(struct alias_link *link, char **fptr)
1455 *fptr = link->data.frag_ptr;
1460 SetStateIn(struct alias_link *link, int state)
1462 /* TCP input state */
1464 case ALIAS_TCP_STATE_DISCONNECTED:
1465 if (link->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED) {
1466 link->expire_time = TCP_EXPIRE_DEAD;
1468 link->expire_time = TCP_EXPIRE_SINGLEDEAD;
1470 link->data.tcp->state.in = state;
1472 case ALIAS_TCP_STATE_CONNECTED:
1473 link->expire_time = TCP_EXPIRE_CONNECTED;
1475 case ALIAS_TCP_STATE_NOT_CONNECTED:
1476 link->data.tcp->state.in = state;
1485 SetStateOut(struct alias_link *link, int state)
1487 /* TCP output state */
1489 case ALIAS_TCP_STATE_DISCONNECTED:
1490 if (link->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED) {
1491 link->expire_time = TCP_EXPIRE_DEAD;
1493 link->expire_time = TCP_EXPIRE_SINGLEDEAD;
1495 link->data.tcp->state.out = state;
1497 case ALIAS_TCP_STATE_CONNECTED:
1498 link->expire_time = TCP_EXPIRE_CONNECTED;
1500 case ALIAS_TCP_STATE_NOT_CONNECTED:
1501 link->data.tcp->state.out = state;
1510 GetStateIn(struct alias_link *link)
1512 /* TCP input state */
1513 return link->data.tcp->state.in;
1518 GetStateOut(struct alias_link *link)
1520 /* TCP output state */
1521 return link->data.tcp->state.out;
1526 GetOriginalAddress(struct alias_link *link)
1528 if (link->src_addr.s_addr == 0)
1529 return aliasAddress;
1531 return(link->src_addr);
1536 GetDestAddress(struct alias_link *link)
1538 return(link->dst_addr);
1543 GetAliasAddress(struct alias_link *link)
1545 if (link->alias_addr.s_addr == 0)
1546 return aliasAddress;
1548 return link->alias_addr;
1553 GetDefaultAliasAddress()
1555 return aliasAddress;
1560 SetDefaultAliasAddress(struct in_addr alias_addr)
1562 aliasAddress = alias_addr;
1567 GetOriginalPort(struct alias_link *link)
1569 return(link->src_port);
1574 GetAliasPort(struct alias_link *link)
1576 return(link->alias_port);
1580 GetDestPort(struct alias_link *link)
1582 return(link->dst_port);
1586 SetAckModified(struct alias_link *link)
1588 /* Indicate that ack numbers have been modified in a TCP connection */
1589 link->data.tcp->state.ack_modified = 1;
1594 GetProxyAddress(struct alias_link *link)
1596 return link->proxy_addr;
1601 SetProxyAddress(struct alias_link *link, struct in_addr addr)
1603 link->proxy_addr = addr;
1608 GetProxyPort(struct alias_link *link)
1610 return link->proxy_port;
1615 SetProxyPort(struct alias_link *link, u_short port)
1617 link->proxy_port = port;
1622 GetAckModified(struct alias_link *link)
1624 /* See if ack numbers have been modified */
1625 return link->data.tcp->state.ack_modified;
1630 GetDeltaAckIn(struct ip *pip, struct alias_link *link)
1633 Find out how much the ack number has been altered for an incoming
1634 TCP packet. To do this, a circular list is ack numbers where the TCP
1635 packet size was altered is searched.
1640 int delta, ack_diff_min;
1643 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1648 for (i=0; i<N_LINK_TCP_DATA; i++)
1650 struct ack_data_record x;
1652 x = link->data.tcp->ack[i];
1657 ack_diff = SeqDiff(x.ack_new, ack);
1660 if (ack_diff_min >= 0)
1662 if (ack_diff < ack_diff_min)
1665 ack_diff_min = ack_diff;
1671 ack_diff_min = ack_diff;
1681 GetDeltaSeqOut(struct ip *pip, struct alias_link *link)
1684 Find out how much the seq number has been altered for an outgoing
1685 TCP packet. To do this, a circular list is ack numbers where the TCP
1686 packet size was altered is searched.
1691 int delta, seq_diff_min;
1694 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1699 for (i=0; i<N_LINK_TCP_DATA; i++)
1701 struct ack_data_record x;
1703 x = link->data.tcp->ack[i];
1708 seq_diff = SeqDiff(x.ack_old, seq);
1711 if (seq_diff_min >= 0)
1713 if (seq_diff < seq_diff_min)
1716 seq_diff_min = seq_diff;
1722 seq_diff_min = seq_diff;
1732 AddSeq(struct ip *pip, struct alias_link *link, int delta)
1735 When a TCP packet has been altered in length, save this
1736 information in a circular list. If enough packets have
1737 been altered, then this list will begin to overwrite itself.
1741 struct ack_data_record x;
1742 int hlen, tlen, dlen;
1745 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
1747 hlen = (pip->ip_hl + tc->th_off) << 2;
1748 tlen = ntohs(pip->ip_len);
1751 x.ack_old = htonl(ntohl(tc->th_seq) + dlen);
1752 x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta);
1756 i = link->data.tcp->state.index;
1757 link->data.tcp->ack[i] = x;
1760 if (i == N_LINK_TCP_DATA)
1761 link->data.tcp->state.index = 0;
1763 link->data.tcp->state.index = i;
1767 SetExpire(struct alias_link *link, int expire)
1771 link->flags &= ~LINK_PERMANENT;
1774 else if (expire == -1)
1776 link->flags |= LINK_PERMANENT;
1778 else if (expire > 0)
1780 link->expire_time = expire;
1784 fprintf(stderr, "PacketAlias/SetExpire(): ");
1785 fprintf(stderr, "error in expire parameter\n");
1790 ClearCheckNewLink(void)
1796 /* Miscellaneous Functions
1799 InitPacketAliasLog()
1800 UninitPacketAliasLog()
1804 Whenever an outgoing or incoming packet is handled, HouseKeeping()
1805 is called to find and remove timed-out aliasing links. Logic exists
1806 to sweep through the entire table and linked list structure
1809 (prototype in alias_local.h)
1820 * Save system time (seconds) in global variable timeStamp for
1821 * use by other functions. This is done so as not to unnecessarily
1822 * waste timeline by making system calls.
1824 gettimeofday(&tv, &tz);
1825 timeStamp = tv.tv_sec;
1827 /* Compute number of spokes (output table link chains) to cover */
1828 n100 = LINK_TABLE_OUT_SIZE * 100 + houseKeepingResidual;
1829 n100 *= timeStamp - lastCleanupTime;
1830 n100 /= ALIAS_CLEANUP_INTERVAL_SECS;
1834 /* Handle different cases */
1835 if (n > ALIAS_CLEANUP_MAX_SPOKES)
1837 n = ALIAS_CLEANUP_MAX_SPOKES;
1838 lastCleanupTime = timeStamp;
1839 houseKeepingResidual = 0;
1842 IncrementalCleanup();
1846 lastCleanupTime = timeStamp;
1847 houseKeepingResidual = n100 - 100*n;
1850 IncrementalCleanup();
1854 fprintf(stderr, "PacketAlias/HouseKeeping(): ");
1855 fprintf(stderr, "something unexpected in time values\n");
1856 lastCleanupTime = timeStamp;
1857 houseKeepingResidual = 0;
1862 /* Init the log file and enable logging */
1864 InitPacketAliasLog(void)
1866 if ((~packetAliasMode & PKT_ALIAS_LOG)
1867 && (monitorFile = fopen("/var/log/alias.log", "w")))
1869 packetAliasMode |= PKT_ALIAS_LOG;
1870 fprintf(monitorFile,
1871 "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
1876 /* Close the log-file and disable logging. */
1878 UninitPacketAliasLog(void)
1881 fclose(monitorFile);
1884 packetAliasMode &= ~PKT_ALIAS_LOG;
1892 /* Outside world interfaces
1894 -- "outside world" means other than alias*.c routines --
1896 PacketAliasRedirectPort()
1897 PacketAliasRedirectAddr()
1898 PacketAliasRedirectDelete()
1899 PacketAliasSetAddress()
1902 PacketAliasSetMode()
1904 (prototypes in alias.h)
1907 /* Redirection from a specific public addr:port to a
1908 a private addr:port */
1910 PacketAliasRedirectPort(struct in_addr src_addr, u_short src_port,
1911 struct in_addr dst_addr, u_short dst_port,
1912 struct in_addr alias_addr, u_short alias_port,
1916 struct alias_link *link;
1921 link_type = LINK_UDP;
1924 link_type = LINK_TCP;
1927 fprintf(stderr, "PacketAliasRedirectPort(): ");
1928 fprintf(stderr, "only TCP and UDP protocols allowed\n");
1932 link = AddLink(src_addr, dst_addr, alias_addr,
1933 src_port, dst_port, alias_port,
1938 link->flags |= LINK_PERMANENT;
1942 fprintf(stderr, "PacketAliasRedirectPort(): "
1943 "call to AddLink() failed\n");
1949 /* Translate PPTP packets to a machine on the inside
1952 PacketAliasPptp(struct in_addr src_addr)
1955 pptpAliasAddr = src_addr; /* Address of the inside PPTP machine */
1962 int GetPptpAlias (struct in_addr* alias_addr)
1965 *alias_addr = pptpAliasAddr;
1967 return pptpAliasFlag;
1970 /* Static address translation */
1972 PacketAliasRedirectAddr(struct in_addr src_addr,
1973 struct in_addr alias_addr)
1975 struct alias_link *link;
1977 link = AddLink(src_addr, nullAddress, alias_addr,
1983 link->flags |= LINK_PERMANENT;
1987 fprintf(stderr, "PacketAliasRedirectAddr(): "
1988 "call to AddLink() failed\n");
1996 PacketAliasRedirectDelete(struct alias_link *link)
1998 /* This is a dangerous function to put in the API,
1999 because an invalid pointer can crash the program. */
2008 PacketAliasSetAddress(struct in_addr addr)
2010 if (packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
2011 && aliasAddress.s_addr != addr.s_addr)
2014 aliasAddress = addr;
2019 PacketAliasSetTarget(struct in_addr target_addr)
2021 targetAddress = target_addr;
2026 PacketAliasInit(void)
2031 static int firstCall = 1;
2035 gettimeofday(&tv, &tz);
2036 timeStamp = tv.tv_sec;
2037 lastCleanupTime = tv.tv_sec;
2038 houseKeepingResidual = 0;
2040 for (i=0; i<LINK_TABLE_OUT_SIZE; i++)
2041 linkTableOut[i] = NULL;
2042 for (i=0; i<LINK_TABLE_IN_SIZE; i++)
2043 linkTableIn[i] = NULL;
2045 atexit(PacketAliasUninit);
2055 aliasAddress.s_addr = 0;
2056 targetAddress.s_addr = 0;
2061 fragmentIdLinkCount = 0;
2062 fragmentPtrLinkCount = 0;
2067 packetAliasMode = PKT_ALIAS_SAME_PORTS
2068 | PKT_ALIAS_USE_SOCKETS
2069 | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
2075 PacketAliasUninit(void) {
2079 UninitPacketAliasLog();
2086 /* Change mode for some operations */
2089 unsigned int flags, /* Which state to bring flags to */
2090 unsigned int mask /* Mask of which flags to affect (use 0 to do a
2091 probe for flag values) */
2094 /* Enable logging? */
2095 if (flags & mask & PKT_ALIAS_LOG)
2097 InitPacketAliasLog(); /* Do the enable */
2099 /* _Disable_ logging? */
2100 if (~flags & mask & PKT_ALIAS_LOG) {
2101 UninitPacketAliasLog();
2105 /* Start punching holes in the firewall? */
2106 if (flags & mask & PKT_ALIAS_PUNCH_FW) {
2109 /* Stop punching holes in the firewall? */
2110 if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
2115 /* Other flags can be set/cleared without special action */
2116 packetAliasMode = (flags & mask) | (packetAliasMode & ~mask);
2117 return packetAliasMode;
2122 PacketAliasCheckNewLink(void)
2124 return newDefaultLink;
2131 Code to support firewall punching. This shouldn't really be in this
2132 file, but making variables global is evil too.
2135 /* Firewall include files */
2136 #include <sys/queue.h>
2138 #include <netinet/ip_fw.h>
2142 static void ClearAllFWHoles(void);
2144 static int fireWallBaseNum; /* The first firewall entry free for our use */
2145 static int fireWallNumNums; /* How many entries can we use? */
2146 static int fireWallActiveNum; /* Which entry did we last use? */
2147 static char *fireWallField; /* bool array for entries */
2149 #define fw_setfield(field, num) \
2152 } /*lint -save -e717 */ while(0) /*lint -restore */
2153 #define fw_clrfield(field, num) \
2156 } /*lint -save -e717 */ while(0) /*lint -restore */
2157 #define fw_tstfield(field, num) ((field)[num])
2160 PacketAliasSetFWBase(unsigned int base, unsigned int num) {
2161 fireWallBaseNum = base;
2162 fireWallNumNums = num;
2167 fireWallField = malloc(fireWallNumNums);
2168 if (fireWallField) {
2169 memset(fireWallField, 0, fireWallNumNums);
2170 if (fireWallFD < 0) {
2171 fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2174 fireWallActiveNum = fireWallBaseNum;
2179 UninitPunchFW(void) {
2181 if (fireWallFD >= 0)
2185 free(fireWallField);
2186 fireWallField = NULL;
2187 packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2190 /* Make a certain link go through the firewall */
2192 PunchFWHole(struct alias_link *link) {
2193 int r; /* Result code */
2194 struct ip_fw rule; /* On-the-fly built rule */
2195 int fwhole; /* Where to punch hole */
2197 /* Don't do anything unless we are asked to */
2198 if ( !(packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2200 link->link_type != LINK_TCP ||
2204 memset(&rule, 0, sizeof rule);
2208 /* Find empty slot */
2209 for (fwhole = fireWallActiveNum;
2210 fwhole < fireWallBaseNum + fireWallNumNums &&
2211 fw_tstfield(fireWallField, fwhole);
2214 if (fwhole >= fireWallBaseNum + fireWallNumNums ||
2215 fw_tstfield(fireWallField, fwhole)) {
2216 for (fwhole = fireWallBaseNum;
2217 fwhole < fireWallActiveNum &&
2218 fw_tstfield(fireWallField, fwhole);
2221 if (fwhole == fireWallActiveNum) {
2222 /* No rule point empty - we can't punch more holes. */
2223 fireWallActiveNum = fireWallBaseNum;
2224 fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2228 /* Start next search at next position */
2229 fireWallActiveNum = fwhole+1;
2231 /* Build generic part of the two rules */
2232 rule.fw_number = fwhole;
2233 rule.fw_nports = 1; /* Number of source ports; dest ports follow */
2234 rule.fw_flg = IP_FW_F_ACCEPT;
2235 rule.fw_prot = IPPROTO_TCP;
2236 rule.fw_smsk.s_addr = INADDR_BROADCAST;
2237 rule.fw_dmsk.s_addr = INADDR_BROADCAST;
2239 /* Build and apply specific part of the rules */
2240 rule.fw_src = GetOriginalAddress(link);
2241 rule.fw_dst = GetDestAddress(link);
2242 rule.fw_uar.fw_pts[0] = ntohs(GetOriginalPort(link));
2243 rule.fw_uar.fw_pts[1] = ntohs(GetDestPort(link));
2245 /* Skip non-bound links - XXX should not be strictly necessary,
2246 but seems to leave hole if not done. Leak of non-bound links?
2247 (Code should be left even if the problem is fixed - it is a
2248 clear optimization) */
2249 if (rule.fw_uar.fw_pts[0] != 0 && rule.fw_uar.fw_pts[1] != 0) {
2250 r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule);
2252 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2253 rule.fw_src = GetDestAddress(link);
2254 rule.fw_dst = GetOriginalAddress(link);
2255 rule.fw_uar.fw_pts[0] = ntohs(GetDestPort(link));
2256 rule.fw_uar.fw_pts[1] = ntohs(GetOriginalPort(link));
2257 r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule);
2259 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2261 /* Indicate hole applied */
2262 link->data.tcp->fwhole = fwhole;
2263 fw_setfield(fireWallField, fwhole);
2266 /* Remove a hole in a firewall associated with a particular alias
2267 link. Calling this too often is harmless. */
2269 ClearFWHole(struct alias_link *link) {
2270 if (link->link_type == LINK_TCP && link->data.tcp) {
2271 int fwhole = link->data.tcp->fwhole; /* Where is the firewall hole? */
2277 memset(&rule, 0, sizeof rule);
2278 rule.fw_number = fwhole;
2279 while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule))
2281 fw_clrfield(fireWallField, fwhole);
2282 link->data.tcp->fwhole = -1;
2286 /* Clear out the entire range dedicated to firewall holes. */
2288 ClearAllFWHoles(void) {
2289 struct ip_fw rule; /* On-the-fly built rule */
2295 memset(&rule, 0, sizeof rule);
2296 for (i = fireWallBaseNum; i < fireWallBaseNum + fireWallNumNums; i++) {
2298 while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule))
2301 memset(fireWallField, 0, fireWallNumNums);