1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2001 Charles Mott <cm@linktel.net> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 Alias_db.c encapsulates all data structures used for storing 31 packet aliasing data. Other parts of the aliasing software 32 access data through functions provided in this file. 33 34 Data storage is based on the notion of a "link", which is 35 established for ICMP echo/reply packets, UDP datagrams and 36 TCP stream connections. A link stores the original source 37 and destination addresses. For UDP and TCP, it also stores 38 source and destination port numbers, as well as an alias 39 port number. Links are also used to store information about 40 fragments. 41 42 There is a facility for sweeping through and deleting old 43 links as new packets are sent through. A simple timeout is 44 used for ICMP and UDP links. TCP links are left alone unless 45 there is an incomplete connection, in which case the link 46 can be deleted after a certain amount of time. 47 48 Initial version: August, 1996 (cjm) 49 50 Version 1.4: September 16, 1996 (cjm) 51 Facility for handling incoming links added. 52 53 Version 1.6: September 18, 1996 (cjm) 54 ICMP data handling simplified. 55 56 Version 1.7: January 9, 1997 (cjm) 57 Fragment handling simplified. 58 Saves pointers for unresolved fragments. 59 Permits links for unspecified remote ports 60 or unspecified remote addresses. 61 Fixed bug which did not properly zero port 62 table entries after a link was deleted. 63 Cleaned up some obsolete comments. 64 65 Version 1.8: January 14, 1997 (cjm) 66 Fixed data type error in StartPoint(). 67 (This error did not exist prior to v1.7 68 and was discovered and fixed by Ari Suutari) 69 70 Version 1.9: February 1, 1997 71 Optionally, connections initiated from packet aliasing host 72 machine will will not have their port number aliased unless it 73 conflicts with an aliasing port already being used. (cjm) 74 75 All options earlier being #ifdef'ed are now available through 76 a new interface, SetPacketAliasMode(). This allows run time 77 control (which is now available in PPP+pktAlias through the 78 'alias' keyword). (ee) 79 80 Added ability to create an alias port without 81 either destination address or port specified. 82 port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee) 83 84 Removed K&R style function headers 85 and general cleanup. (ee) 86 87 Added packetAliasMode to replace compiler #defines's (ee) 88 89 Allocates sockets for partially specified 90 ports if ALIAS_USE_SOCKETS defined. (cjm) 91 92 Version 2.0: March, 1997 93 SetAliasAddress() will now clean up alias links 94 if the aliasing address is changed. (cjm) 95 96 PacketAliasPermanentLink() function added to support permanent 97 links. (J. Fortes suggested the need for this.) 98 Examples: 99 100 (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port 101 102 (192.168.0.2, port 21) <-> alias port 3604, known dest addr 103 unknown dest port 104 105 These permanent links allow for incoming connections to 106 machines on the local network. They can be given with a 107 user-chosen amount of specificity, with increasing specificity 108 meaning more security. (cjm) 109 110 Quite a bit of rework to the basic engine. The portTable[] 111 array, which kept track of which ports were in use was replaced 112 by a table/linked list structure. (cjm) 113 114 SetExpire() function added. (cjm) 115 116 DeleteLink() no longer frees memory association with a pointer 117 to a fragment (this bug was first recognized by E. Eklund in 118 v1.9). 119 120 Version 2.1: May, 1997 (cjm) 121 Packet aliasing engine reworked so that it can handle 122 multiple external addresses rather than just a single 123 host address. 124 125 PacketAliasRedirectPort() and PacketAliasRedirectAddr() 126 added to the API. The first function is a more generalized 127 version of PacketAliasPermanentLink(). The second function 128 implements static network address translation. 129 130 Version 3.2: July, 2000 (salander and satoh) 131 Added FindNewPortGroup to get contiguous range of port values. 132 133 Added QueryUdpTcpIn and QueryUdpTcpOut to look for an aliasing 134 link but not actually add one. 135 136 Added FindRtspOut, which is closely derived from FindUdpTcpOut, 137 except that the alias port (from FindNewPortGroup) is provided 138 as input. 139 140 See HISTORY file for additional revisions. 141 */ 142 143 #ifndef _ALIAS_DB_H_ 144 #define _ALIAS_DB_H_ 145 146 147 /* 148 Constants (note: constants are also defined 149 near relevant functions or structs) 150 */ 151 152 /* Timeouts (in seconds) for different link types */ 153 #define ICMP_EXPIRE_TIME 60 154 #define UDP_EXPIRE_TIME 60 155 #define PROTO_EXPIRE_TIME 60 156 #define FRAGMENT_ID_EXPIRE_TIME 10 157 #define FRAGMENT_PTR_EXPIRE_TIME 30 158 159 /* TCP link expire time for different cases */ 160 /* When the link has been used and closed - minimal grace time to 161 allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */ 162 #ifndef TCP_EXPIRE_DEAD 163 #define TCP_EXPIRE_DEAD 10 164 #endif 165 166 /* When the link has been used and closed on one side - the other side 167 is allowed to still send data */ 168 #ifndef TCP_EXPIRE_SINGLEDEAD 169 #define TCP_EXPIRE_SINGLEDEAD 90 170 #endif 171 172 /* When the link isn't yet up */ 173 #ifndef TCP_EXPIRE_INITIAL 174 #define TCP_EXPIRE_INITIAL 300 175 #endif 176 177 /* When the link is up */ 178 #ifndef TCP_EXPIRE_CONNECTED 179 #define TCP_EXPIRE_CONNECTED 86400 180 #endif 181 182 /* Dummy port number codes used for FindLinkIn/Out() and AddLink(). 183 These constants can be anything except zero, which indicates an 184 unknown port number. */ 185 186 #define NO_DEST_PORT 1 187 #define NO_SRC_PORT 1 188 189 /* Matches any/unknown address in FindLinkIn/Out() and AddLink(). */ 190 static struct in_addr const ANY_ADDR = { INADDR_ANY }; 191 192 /* Data Structures 193 194 The fundamental data structure used in this program is 195 "struct alias_link". Whenever a TCP connection is made, 196 a UDP datagram is sent out, or an ICMP echo request is made, 197 a link record is made (if it has not already been created). 198 The link record is identified by the source address/port 199 and the destination address/port. In the case of an ICMP 200 echo request, the source port is treated as being equivalent 201 with the 16-bit ID number of the ICMP packet. 202 203 The link record also can store some auxiliary data. For 204 TCP connections that have had sequence and acknowledgment 205 modifications, data space is available to track these changes. 206 A state field is used to keep track in changes to the TCP 207 connection state. ID numbers of fragments can also be 208 stored in the auxiliary space. Pointers to unresolved 209 fragments can also be stored. 210 211 The link records support several independent chainings. Lookup 212 tables for input and out tables hold the initial pointers 213 the link chains. On input, the lookup table indexes on alias 214 port and link type. On output, the lookup table indexes on 215 source address, destination address, source port, destination 216 port and link type. A internal_endpoint table is used for 217 endpoint-independent mapping, and indexes on source address, 218 source port and link type. 219 */ 220 221 /* used to save changes to ACK/sequence numbers */ 222 struct ack_data_record { 223 u_long ack_old; 224 u_long ack_new; 225 int delta; 226 int active; 227 }; 228 229 /* Information about TCP connection */ 230 struct tcp_state { 231 int in; /* State for outside -> inside */ 232 int out; /* State for inside -> outside */ 233 int index; /* Index to ACK data array */ 234 /* Indicates whether ACK and sequence numbers been modified */ 235 int ack_modified; 236 }; 237 238 /* Number of distinct ACK number changes 239 * saved for a modified TCP stream */ 240 #define N_LINK_TCP_DATA 3 241 struct tcp_dat { 242 struct tcp_state state; 243 struct ack_data_record ack[N_LINK_TCP_DATA]; 244 /* Which firewall record is used for this hole? */ 245 int fwhole; 246 }; 247 248 /* LSNAT server pool (circular list) */ 249 struct server { 250 struct in_addr addr; 251 u_short port; 252 struct server *next; 253 }; 254 255 /* Main data structure */ 256 struct alias_link { 257 struct libalias *la; 258 /* Address and port information */ 259 struct in_addr src_addr; 260 struct in_addr dst_addr; 261 struct in_addr alias_addr; 262 struct in_addr proxy_addr; 263 u_short src_port; 264 u_short dst_port; 265 u_short alias_port; 266 u_short proxy_port; 267 struct server *server; 268 /* Type of link: TCP, UDP, ICMP, proto, frag */ 269 int link_type; 270 /* values for link_type */ 271 #define LINK_ICMP IPPROTO_ICMP 272 #define LINK_UDP IPPROTO_UDP 273 #define LINK_TCP IPPROTO_TCP 274 #define LINK_FRAGMENT_ID (IPPROTO_MAX + 1) 275 #define LINK_FRAGMENT_PTR (IPPROTO_MAX + 2) 276 #define LINK_ADDR (IPPROTO_MAX + 3) 277 #define LINK_PPTP (IPPROTO_MAX + 4) 278 279 int flags; /* indicates special characteristics */ 280 int pflags; /* protocol-specific flags */ 281 /* flag bits */ 282 #define LINK_UNKNOWN_DEST_PORT 0x01 283 #define LINK_UNKNOWN_DEST_ADDR 0x02 284 #define LINK_PERMANENT 0x04 285 #define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */ 286 #define LINK_UNFIREWALLED 0x08 287 288 int timestamp; /* Time link was last accessed */ 289 uint64_t seq; /* Insertion order within the instance */ 290 #ifndef NO_USE_SOCKETS 291 int sockfd; /* socket descriptor */ 292 #endif 293 /* Linked list of pointers for input and output lookup tables */ 294 union { 295 struct { 296 SPLAY_ENTRY(alias_link) out; 297 union { 298 /* in grp->partial */ 299 LIST_ENTRY (alias_link) in; 300 /* in grp->full */ 301 RB_ENTRY(alias_link) in_full; 302 }; 303 SPLAY_ENTRY(alias_link) internal_endpoint; 304 } all; 305 struct { 306 LIST_ENTRY (alias_link) list; 307 } pptp; 308 }; 309 struct { 310 TAILQ_ENTRY(alias_link) list; 311 int time; /* Expire time for link */ 312 } expire; 313 /* Auxiliary data */ 314 union { 315 char *frag_ptr; 316 struct in_addr frag_addr; 317 struct tcp_dat *tcp; 318 } data; 319 }; 320 321 /* Clean up procedure. */ 322 static void finishoff(void); 323 324 /* Internal utility routines (used only in alias_db.c) 325 326 Lookup table starting points: 327 StartPointIn() -- link table initial search point for 328 incoming packets 329 StartPointOut() -- link table initial search point for 330 outgoing packets 331 332 Miscellaneous: 333 SeqDiff() -- difference between two TCP sequences 334 ShowAliasStats() -- send alias statistics to a monitor file 335 */ 336 337 /* Local prototypes */ 338 static struct group_in * 339 StartPointIn(struct libalias *, struct in_addr, u_short, int, int); 340 static int SeqDiff(u_long, u_long); 341 342 #ifndef NO_FW_PUNCH 343 /* Firewall control */ 344 static void InitPunchFW(struct libalias *); 345 static void UninitPunchFW(struct libalias *); 346 static void ClearFWHole(struct alias_link *); 347 348 #endif 349 350 /* Log file control */ 351 static void ShowAliasStats(struct libalias *); 352 static int InitPacketAliasLog(struct libalias *); 353 static void UninitPacketAliasLog(struct libalias *); 354 355 void SctpShowAliasStats(struct libalias *la); 356 357 358 /* Splay handling */ 359 static inline int 360 cmp_out(struct alias_link *a, struct alias_link *b) { 361 int i = a->src_port - b->src_port; 362 if (i != 0) return (i); 363 if (a->src_addr.s_addr > b->src_addr.s_addr) return (1); 364 if (a->src_addr.s_addr < b->src_addr.s_addr) return (-1); 365 if (a->dst_addr.s_addr > b->dst_addr.s_addr) return (1); 366 if (a->dst_addr.s_addr < b->dst_addr.s_addr) return (-1); 367 i = a->dst_port - b->dst_port; 368 if (i != 0) return (i); 369 i = a->link_type - b->link_type; 370 return (i); 371 } 372 SPLAY_PROTOTYPE(splay_out, alias_link, all.out, cmp_out); 373 374 static inline int 375 cmp_in(struct group_in *a, struct group_in *b) { 376 int i = a->alias_port - b->alias_port; 377 if (i != 0) return (i); 378 i = a->link_type - b->link_type; 379 if (i != 0) return (i); 380 if (a->alias_addr.s_addr > b->alias_addr.s_addr) return (1); 381 if (a->alias_addr.s_addr < b->alias_addr.s_addr) return (-1); 382 return (0); 383 } 384 SPLAY_PROTOTYPE(splay_in, group_in, in, cmp_in); 385 386 static inline int 387 cmp_internal_endpoint(struct alias_link *a, struct alias_link *b) { 388 int i = a->link_type - b->link_type; 389 if (i != 0) return (i); 390 if (a->src_addr.s_addr > b->src_addr.s_addr) return (1); 391 if (a->src_addr.s_addr < b->src_addr.s_addr) return (-1); 392 i = a->src_port - b->src_port; 393 return (i); 394 } 395 SPLAY_PROTOTYPE(splay_internal_endpoint, alias_link, all.internal_endpoint, 396 cmp_internal_endpoint); 397 398 /* Internal routines for finding, deleting and adding links 399 400 Port Allocation: 401 GetNewPort() -- find and reserve new alias port number 402 GetSocket() -- try to allocate a socket for a given port 403 404 Link creation and deletion: 405 CleanupAliasData() - remove all link chains from lookup table 406 CleanupLink() - look for a stale link 407 DeleteLink() - remove link 408 AddLink() - add link 409 ReLink() - change link 410 411 Link search: 412 FindLinkOut() - find link for outgoing packets 413 FindLinkIn() - find link for incoming packets 414 FindLinkByInternalEndpoint() - find link by a packet's internal endpoint 415 416 Port search: 417 FindNewPortGroup() - find an available group of ports 418 */ 419 420 /* Local prototypes */ 421 static int GetNewPort(struct libalias *, struct alias_link *, int); 422 #ifndef NO_USE_SOCKETS 423 static u_short GetSocket(struct libalias *, u_short, int *, int); 424 #endif 425 static void CleanupAliasData(struct libalias *, int); 426 static void CleanupLink(struct libalias *, struct alias_link **, int); 427 static void DeleteLink(struct alias_link **, int); 428 static struct alias_link * 429 UseLink(struct libalias *, struct alias_link *); 430 431 static struct alias_link * 432 ReLink(struct alias_link *, 433 struct in_addr, struct in_addr, struct in_addr, 434 u_short, u_short, int, int, int); 435 436 static struct alias_link * 437 FindLinkOut(struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); 438 439 static struct alias_link * 440 FindLinkIn(struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); 441 442 static struct alias_link * 443 FindLinkByInternalEndpoint(struct libalias *, struct in_addr, u_short, int); 444 445 static u_short _RandomPort(struct libalias *la); 446 447 #define GET_NEW_PORT_MAX_ATTEMPTS 20 448 449 450 #ifndef NO_FW_PUNCH 451 452 static void ClearAllFWHoles(struct libalias *la); 453 454 #define fw_setfield(la, field, num) \ 455 do { \ 456 (field)[(num) - la->fireWallBaseNum] = 1; \ 457 } /*lint -save -e717 */ while(0)/* lint -restore */ 458 459 #define fw_clrfield(la, field, num) \ 460 do { \ 461 (field)[(num) - la->fireWallBaseNum] = 0; \ 462 } /*lint -save -e717 */ while(0)/* lint -restore */ 463 464 #define fw_tstfield(la, field, num) ((field)[(num) - la->fireWallBaseNum]) 465 466 #endif /* !NO_FW_PUNCH */ 467 468 #endif /* _ALIAS_DB_H_ */ 469