1.\"- 2.\" Copyright (c) 2001 Charles Mott <cm@linktel.net> 3.\" All rights reserved. 4.\" 5.\" Redistribution and use in source and binary forms, with or without 6.\" modification, are permitted provided that the following conditions 7.\" are met: 8.\" 1. Redistributions of source code must retain the above copyright 9.\" notice, this list of conditions and the following disclaimer. 10.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" notice, this list of conditions and the following disclaimer in the 12.\" documentation and/or other materials provided with the distribution. 13.\" 14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24.\" SUCH DAMAGE. 25.\" 26.Dd November 29, 2024 27.Dt LIBALIAS 3 28.Os 29.Sh NAME 30.Nm libalias 31.Nd packet aliasing library for masquerading and network address translation 32.Sh SYNOPSIS 33.In sys/types.h 34.In netinet/in.h 35.In alias.h 36.Pp 37Function prototypes are given in the main body of the text. 38.Sh DESCRIPTION 39The 40.Nm 41library is a collection of functions for aliasing and de-aliasing of IP 42packets, intended for masquerading and network address translation (NAT). 43.Sh INTRODUCTION 44This library is a moderately portable set of functions designed to assist 45in the process of IP masquerading and network address translation. 46Outgoing packets from a local network with unregistered IP addresses can 47be aliased to appear as if they came from an accessible IP address. 48Incoming packets are then de-aliased so that they are sent to the correct 49machine on the local network. 50.Pp 51A certain amount of flexibility is built into the packet aliasing engine. 52In the simplest mode of operation, a many-to-one address mapping takes 53place between the local network and the packet aliasing host. 54This is known as IP masquerading. 55In addition, one-to-one mappings between local and public addresses can 56also be implemented, which is known as static NAT. 57In between these extremes, different groups of private addresses can be 58linked to different public addresses, comprising several distinct 59many-to-one mappings. 60Also, a given public address and port can be statically redirected to a 61private address/port. 62.Sh INITIALIZATION AND CONTROL 63One special function, 64.Fn LibAliasInit , 65must always be called before any packet handling may be performed, and 66the returned instance pointer must be passed to all the other functions. 67Normally, the 68.Fn LibAliasSetAddress 69function is called afterwards, to set the default aliasing address. 70In addition, the operating mode of the packet aliasing engine can be 71customized by calling 72.Fn LibAliasSetMode . 73.Pp 74.Ft "struct libalias *" 75.Fn LibAliasInit "struct libalias *" 76.Bd -ragged -offset indent 77This function is used to initialize 78internal data structures. 79When called the first time, a 80.Dv NULL 81pointer should be passed as an argument. 82The following mode bits are always set after calling 83.Fn LibAliasInit . 84See the description of 85.Fn LibAliasSetMode 86below for the meaning of these mode bits. 87.Pp 88.Bl -item -offset indent -compact 89.It 90.Dv PKT_ALIAS_SAME_PORTS 91.It 92.Dv PKT_ALIAS_USE_SOCKETS 93.It 94.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE 95.El 96.Pp 97This function will always return the packet aliasing engine to the same 98initial state. 99The 100.Fn LibAliasSetAddress 101function is normally called afterwards, and any desired changes from the 102default mode bits listed above require a call to 103.Fn LibAliasSetMode . 104.Pp 105It is mandatory that this function be called at the beginning of a program 106prior to any packet handling. 107.Ed 108.Pp 109.Ft void 110.Fn LibAliasUninit "struct libalias *" 111.Bd -ragged -offset indent 112This function has no return value and is used to clear any 113resources attached to internal data structures. 114.Pp 115This function should be called when a program stops using the aliasing 116engine; amongst other things, it clears out any firewall holes. 117To provide backwards compatibility and extra security, it is added to 118the 119.Xr atexit 3 120chain by 121.Fn LibAliasInit . 122.Ed 123.Pp 124.Ft void 125.Fn LibAliasSetAddress "struct libalias *" "struct in_addr addr" 126.Bd -ragged -offset indent 127This function sets the source address to which outgoing packets from the 128local area network are aliased. 129All outgoing packets are re-mapped to this address unless overridden by a 130static address mapping established by 131.Fn LibAliasRedirectAddr . 132If this function has not been called, and no static rules match, an outgoing 133packet retains its source address. 134.Pp 135If the 136.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE 137mode bit is set (the default mode of operation), then the internal aliasing 138link tables will be reset any time the aliasing address changes. 139This is useful for interfaces such as 140.Xr ppp 8 , 141where the IP 142address may or may not change on successive dial-up attempts. 143.Pp 144If the 145.Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE 146mode bit is set to zero, this function can also be used to dynamically change 147the aliasing address on a packet-to-packet basis (it is a low overhead call). 148.Pp 149It is mandatory that this function be called prior to any packet handling. 150.Ed 151.Pp 152.Ft unsigned int 153.Fn LibAliasSetMode "struct libalias *" "unsigned int flags" "unsigned int mask" 154.Bd -ragged -offset indent 155This function sets or clears mode bits 156according to the value of 157.Fa flags . 158Only bits marked in 159.Fa mask 160are affected. 161The following mode bits are defined in 162.In alias.h : 163.Bl -tag -width indent 164.It Dv PKT_ALIAS_LOG 165Enables logging into 166.Pa /var/log/alias.log . 167Each time an aliasing link is created or deleted, the log file is appended to 168with the current number of ICMP, TCP and UDP links. 169Mainly useful for debugging when the log file is viewed continuously with 170.Xr tail 1 . 171.It Dv PKT_ALIAS_DENY_INCOMING 172If this mode bit is set, all incoming packets associated with new TCP 173connections or new UDP transactions will be marked for being ignored 174.Po 175.Fn LibAliasIn 176returns 177.Dv PKT_ALIAS_IGNORED 178code 179.Pc 180by the calling program. 181Response packets to connections or transactions initiated from the packet 182aliasing host or local network will be unaffected. 183This mode bit is useful for implementing a one-way firewall. 184.It Dv PKT_ALIAS_SAME_PORTS 185If this mode bit is set, the packet-aliasing engine will attempt to leave 186the alias port numbers unchanged from the actual local port numbers. 187This can be done as long as the quintuple (proto, alias addr, alias port, 188remote addr, remote port) is unique. 189If a conflict exists, a new aliasing port number is chosen even if this 190mode bit is set. 191.It Dv PKT_ALIAS_USE_SOCKETS 192This bit should be set when the packet aliasing host originates network 193traffic as well as forwards it. 194When the packet aliasing host is waiting for a connection from an unknown 195host address or unknown port number (e.g.\& an FTP data connection), this 196mode bit specifies that a socket be allocated as a place holder to prevent 197port conflicts. 198Once a connection is established, usually within a minute or so, the socket 199is closed. 200.It Dv PKT_ALIAS_UNREGISTERED_ONLY 201If this mode bit is set, traffic on the local network which does not 202originate from unregistered address spaces will be ignored. 203Standard Class A, B and C unregistered addresses are: 204.Pp 20510.0.0.0 -> 10.255.255.255 (Class A subnet) 206172.16.0.0 -> 172.31.255.255 (Class B subnets) 207192.168.0.0 -> 192.168.255.255 (Class C subnets) 208.Pp 209This option is useful in the case that the packet aliasing host has both 210registered and unregistered subnets on different interfaces. 211The registered subnet is fully accessible to the outside world, so traffic 212from it does not need to be passed through the packet aliasing engine. 213.It Dv PKT_ALIAS_UNREGISTERED_CGN 214Like PKT_ALIAS_UNREGISTERED_ONLY, but includes the RFC 6598 (Carrier Grade 215NAT) subnet as follows: 216.Pp 217100.64.0.0 -> 100.127.255.255 (RFC 6598 subnet) 218.It Dv PKT_ALIAS_RESET_ON_ADDR_CHANGE 219When this mode bit is set and 220.Fn LibAliasSetAddress 221is called to change the aliasing address, the internal link table of the 222packet aliasing engine will be cleared. 223This operating mode is useful for 224.Xr ppp 8 225links where the interface address can sometimes change or remain the same 226between dial-up attempts. 227If this mode bit is not set, the link table will never be reset in the event 228of an address change. 229.It Dv PKT_ALIAS_PUNCH_FW 230This option makes 231.Nm 232.Dq punch holes 233in an 234.Xr ipfirewall 4 - 235based firewall for FTP/IRC DCC connections. 236The holes punched are bound by from/to IP address and port; it will not be 237possible to use a hole for another connection. 238A hole is removed when the connection that uses it dies. 239To cater to unexpected death of a program using 240.Nm 241(e.g.\& kill -9), 242changing the state of the flag will clear the entire firewall range 243allocated for holes. 244This clearing will also happen on the initial call to 245.Fn LibAliasSetFWBase , 246which must happen prior to setting this flag. 247.It Dv PKT_ALIAS_REVERSE 248This option makes 249.Nm 250reverse the way it handles incoming and outgoing packets, allowing it 251to be fed with data that passes through the internal interface rather 252than the external one. 253.It Dv PKT_ALIAS_PROXY_ONLY 254This option tells 255.Nm 256to obey transparent proxy rules only. 257Normal packet aliasing is not performed. 258See 259.Fn LibAliasProxyRule 260below for details. 261.It Dv PKT_ALIAS_SKIP_GLOBAL 262This option is used by 263.Pa ipfw_nat 264only. 265Specifying it as a flag to 266.Fn LibAliasSetMode 267has no effect. 268See section 269.Sx NETWORK ADDRESS TRANSLATION 270in 271.Xr ipfw 8 272for more details. 273.It Dv PKT_ALIAS_UDP_EIM 274When this bit is set, UDP uses endpoint-independent mapping (EIM), as per 275RFC 4787 ("full cone" NAT of RFC 3489). 276All packets from the same internal address:port are mapped to the same NAT 277address:port, regardless of their destination address:port. 278If filtering rules allow, and if 279.Em PKT_ALIAS_DENY_INCOMING 280is unset, any other external address:port can 281also send to the internal address:port through its mapped NAT address:port. 282This is more compatible with applications, and can reduce the need for port 283forwarding, but less scalable as each NAT address:port can only be 284concurrently used by at most one internal address:port. 285.Pp 286When this bit is unset, UDP packets use endpoint-dependent mapping (EDM) 287("symmetric" NAT). 288Each connection from a particular internal address:port to different 289external addresses:ports is mapped to a random and unpredictable NAT 290address:port. 291Two appplications behind EDM NATs can only connect to each other 292by port forwarding on the NAT, or tunnelling through an in-between server. 293.El 294.Ed 295.Pp 296.Ft void 297.Fn LibAliasSetFWBase "struct libalias *" "unsigned int base" "unsigned int num" 298.Bd -ragged -offset indent 299Set the firewall range allocated for punching firewall holes (with the 300.Dv PKT_ALIAS_PUNCH_FW 301flag). 302The range is cleared for all rules on initialization. 303.Ed 304.Pp 305.Ft void 306.Fn LibAliasSkinnyPort "struct libalias *" "unsigned int port" 307.Bd -ragged -offset indent 308Set the TCP port used by the Skinny Station protocol. 309Skinny is used by Cisco IP phones to communicate with 310Cisco Call Managers to set up voice over IP calls. 311If this is not set, Skinny aliasing will not be done. 312The typical port used by Skinny is 2000. 313.Ed 314.Sh PACKET HANDLING 315The packet handling functions are used to modify incoming (remote to local) 316and outgoing (local to remote) packets. 317The calling program is responsible for receiving and sending packets via 318network interfaces. 319.Pp 320Along with 321.Fn LibAliasInit 322and 323.Fn LibAliasSetAddress , 324the two packet handling functions, 325.Fn LibAliasIn 326and 327.Fn LibAliasOut , 328comprise the minimal set of functions needed for a basic IP masquerading 329implementation. 330.Pp 331.Ft int 332.Fn LibAliasIn "struct libalias *" "void *buffer" "int maxpacketsize" 333.Bd -ragged -offset indent 334An incoming packet coming from a remote machine to the local network is 335de-aliased by this function. 336The IP packet is pointed to by 337.Fa buffer , 338and 339.Fa maxpacketsize 340indicates the size of the data structure containing the packet and should 341be at least as large as the actual packet size. 342.Pp 343Return codes: 344.Bl -tag -width indent 345.It Dv PKT_ALIAS_OK 346The packet aliasing process was successful. 347.It Dv PKT_ALIAS_IGNORED 348The packet was ignored and not de-aliased. 349This can happen if the protocol is unrecognized, as for an ICMP message 350type that is not handled, or if incoming packets for new connections are being 351ignored (if the 352.Dv PKT_ALIAS_DENY_INCOMING 353mode bit was set using 354.Fn LibAliasSetMode ) . 355.It Dv PKT_ALIAS_UNRESOLVED_FRAGMENT 356This is returned when a fragment cannot be resolved because the header 357fragment has not been sent yet. 358In this situation, fragments must be saved with 359.Fn LibAliasSaveFragment 360until a header fragment is found. 361.It Dv PKT_ALIAS_FOUND_HEADER_FRAGMENT 362The packet aliasing process was successful, and a header fragment was found. 363This is a signal to retrieve any unresolved fragments with 364.Fn LibAliasGetFragment 365and de-alias them with 366.Fn LibAliasFragmentIn . 367.It Dv PKT_ALIAS_ERROR 368An internal error within the packet aliasing engine occurred. 369.El 370.Ed 371.Pp 372.Ft int 373.Fn LibAliasOut "struct libalias *" "void *buffer" "int maxpacketsize" 374.Bd -ragged -offset indent 375An outgoing packet coming from the local network to a remote machine is 376aliased by this function. 377The IP packet is pointed to by 378.Fa buffer , 379and 380.Fa maxpacketsize 381indicates the maximum packet size permissible should the packet length be 382changed. 383IP encoding protocols place address and port information in the encapsulated 384data stream which has to be modified and can account for changes in packet 385length. 386Well known examples of such protocols are FTP and IRC DCC. 387.Pp 388Return codes: 389.Bl -tag -width indent 390.It Dv PKT_ALIAS_OK 391The packet aliasing process was successful. 392.It Dv PKT_ALIAS_IGNORED 393The packet was ignored and not aliased. 394This can happen if the protocol is unrecognized, or possibly an ICMP message 395type is not handled. 396.It Dv PKT_ALIAS_ERROR 397An internal error within the packet aliasing engine occurred. 398.El 399.Ed 400.Sh PORT AND ADDRESS REDIRECTION 401The functions described in this section allow machines on the local network 402to be accessible in some degree to new incoming connections from the external 403network. 404Individual ports can be re-mapped or static network address translations can 405be designated. 406.Pp 407.Ft struct alias_link * 408.Fo LibAliasRedirectPort 409.Fa "struct libalias *" 410.Fa "struct in_addr local_addr" 411.Fa "u_short local_port" 412.Fa "struct in_addr remote_addr" 413.Fa "u_short remote_port" 414.Fa "struct in_addr alias_addr" 415.Fa "u_short alias_port" 416.Fa "u_char proto" 417.Fc 418.Bd -ragged -offset indent 419This function specifies that traffic from a given remote address/port to 420an alias address/port be redirected to a specified local address/port. 421The parameter 422.Fa proto 423can be either 424.Dv IPPROTO_TCP 425or 426.Dv IPPROTO_UDP , 427as defined in 428.In netinet/in.h . 429.Pp 430If 431.Fa local_addr 432or 433.Fa alias_addr 434is zero, this indicates that the packet aliasing address as established 435by 436.Fn LibAliasSetAddress 437is to be used. 438Even if 439.Fn LibAliasSetAddress 440is called to change the address after 441.Fn LibAliasRedirectPort 442is called, a zero reference will track this change. 443.Pp 444If the link is further set up to operate with load sharing, then 445.Fa local_addr 446and 447.Fa local_port 448are ignored, and are selected dynamically from the server pool, as described in 449.Fn LibAliasAddServer 450below. 451.Pp 452If 453.Fa remote_addr 454is zero, this indicates to redirect packets from any remote address. 455Likewise, if 456.Fa remote_port 457is zero, this indicates to redirect packets originating from any remote 458port number. 459The remote port specification will almost always be zero, but non-zero 460remote addresses can sometimes be useful for firewalling. 461If two calls to 462.Fn LibAliasRedirectPort 463overlap in their address/port specifications, then the most recent call 464will have precedence. 465.Pp 466This function returns a pointer which can subsequently be used by 467.Fn LibAliasRedirectDelete . 468If 469.Dv NULL 470is returned, then the function call did not complete successfully. 471.Pp 472All port numbers should be in network address byte order, so it is necessary 473to use 474.Xr htons 3 475to convert these parameters from internally readable numbers to network byte 476order. 477Addresses are also in network byte order, which is implicit in the use of the 478.Fa struct in_addr 479data type. 480.Ed 481.Pp 482.Ft struct alias_link * 483.Fo LibAliasRedirectAddr 484.Fa "struct libalias *" 485.Fa "struct in_addr local_addr" 486.Fa "struct in_addr alias_addr" 487.Fc 488.Bd -ragged -offset indent 489This function designates that all incoming traffic to 490.Fa alias_addr 491be redirected to 492.Fa local_addr . 493Similarly, all outgoing traffic from 494.Fa local_addr 495is aliased to 496.Fa alias_addr . 497.Pp 498If 499.Fa local_addr 500or 501.Fa alias_addr 502is zero, this indicates that the packet aliasing address as established by 503.Fn LibAliasSetAddress 504is to be used. 505Even if 506.Fn LibAliasSetAddress 507is called to change the address after 508.Fn LibAliasRedirectAddr 509is called, a zero reference will track this change. 510.Pp 511If the link is further set up to operate with load sharing, then the 512.Fa local_addr 513argument is ignored, and is selected dynamically from the server pool, 514as described in 515.Fn LibAliasAddServer 516below. 517.Pp 518If subsequent calls to 519.Fn LibAliasRedirectAddr 520use the same aliasing address, all new incoming traffic to this aliasing 521address will be redirected to the local address made in the last function 522call. 523New traffic generated by any of the local machines, designated in the 524several function calls, will be aliased to the same address. 525Consider the following example: 526.Pp 527LibAliasRedirectAddr(la, inet_aton("192.168.0.2"), 528 inet_aton("141.221.254.101")); 529LibAliasRedirectAddr(la, inet_aton("192.168.0.3"), 530 inet_aton("141.221.254.101")); 531LibAliasRedirectAddr(la, inet_aton("192.168.0.4"), 532 inet_aton("141.221.254.101")); 533.Pp 534Any outgoing connections such as 535.Xr telnet 1 536or 537.Xr ftp 1 538from 192.168.0.2, 192.168.0.3 and 192.168.0.4 will appear to come from 539141.221.254.101. 540Any incoming connections to 141.221.254.101 will be directed to 192.168.0.4. 541.Pp 542Any calls to 543.Fn LibAliasRedirectPort 544will have precedence over address mappings designated by 545.Fn LibAliasRedirectAddr . 546.Pp 547This function returns a pointer which can subsequently be used by 548.Fn LibAliasRedirectDelete . 549If 550.Dv NULL 551is returned, then the function call did not complete successfully. 552.Ed 553.Pp 554.Ft int 555.Fo LibAliasAddServer 556.Fa "struct libalias *" 557.Fa "struct alias_link *link" 558.Fa "struct in_addr addr" 559.Fa "u_short port" 560.Fc 561.Bd -ragged -offset indent 562This function sets the 563.Fa link 564up for Load Sharing using IP Network Address Translation (RFC 2391, LSNAT). 565LSNAT operates as follows. 566A client attempts to access a server by using the server virtual address. 567The LSNAT router transparently redirects the request to one of the hosts 568in the server pool, using a real-time load sharing algorithm. 569Multiple sessions may be initiated from the same client, and each session 570could be directed to a different host based on the load balance across server 571pool hosts when the sessions are initiated. 572If load sharing is desired for just a few specific services, the configuration 573on LSNAT could be defined to restrict load sharing to just the services 574desired. 575.Pp 576Currently, only the simplest selection algorithm is implemented, where a 577host is selected on a round-robin basis only, without regard to load on 578the host. 579.Pp 580First, the 581.Fa link 582is created by either 583.Fn LibAliasRedirectPort 584or 585.Fn LibAliasRedirectAddr . 586Then, 587.Fn LibAliasAddServer 588is called multiple times to add entries to the 589.Fa link Ns 's 590server pool. 591.Pp 592For links created with 593.Fn LibAliasRedirectAddr , 594the 595.Fa port 596argument is ignored and could have any value, e.g.\& htons(~0). 597.Pp 598This function returns 0 on success, \-1 otherwise. 599.Ed 600.Pp 601.Ft int 602.Fn LibAliasRedirectDynamic "struct libalias *" "struct alias_link *link" 603.Bd -ragged -offset indent 604This function marks the specified static redirect rule entered by 605.Fn LibAliasRedirectPort 606as dynamic. 607This can be used to e.g.\& dynamically redirect a single TCP connection, 608after which the rule is removed. 609Only fully specified links can be made dynamic. 610(See the 611.Sx STATIC AND DYNAMIC LINKS 612and 613.Sx PARTIALLY SPECIFIED ALIASING LINKS 614sections below for a definition of static vs.\& dynamic, 615and partially vs.\& fully specified links.) 616.Pp 617This function returns 0 on success, \-1 otherwise. 618.Ed 619.Pp 620.Ft void 621.Fn LibAliasRedirectDelete "struct libalias *" "struct alias_link *link" 622.Bd -ragged -offset indent 623This function will delete a specific static redirect rule entered by 624.Fn LibAliasRedirectPort 625or 626.Fn LibAliasRedirectAddr . 627The parameter 628.Fa link 629is the pointer returned by either of the redirection functions. 630If an invalid pointer is passed to 631.Fn LibAliasRedirectDelete , 632then a program crash or unpredictable operation could result, so 633care is needed when using this function. 634.Ed 635.Pp 636.Ft int 637.Fn LibAliasProxyRule "struct libalias *" "const char *cmd" 638.Bd -ragged -offset indent 639The passed 640.Fa cmd 641string consists of one or more pairs of words. 642The first word in each pair is a token and the second is the value that 643should be applied for that token. 644Tokens and their argument types are as follows: 645.Bl -tag -width indent 646.It Cm type encode_ip_hdr | encode_tcp_stream | no_encode 647In order to support transparent proxying, it is necessary to somehow 648pass the original address and port information into the new destination 649server. 650If 651.Cm encode_ip_hdr 652is specified, the original destination address and port are passed 653as an extra IP option. 654If 655.Cm encode_tcp_stream 656is specified, the original destination address and port are passed 657as the first piece of data in the TCP stream in the format 658.Dq Li DEST Ar IP port . 659.It Cm port Ar portnum 660Only packets with the destination port 661.Ar portnum 662are proxied. 663.It Cm server Ar host Ns Op : Ns Ar portnum 664This specifies the 665.Ar host 666and 667.Ar portnum 668that the data is to be redirected to. 669.Ar host 670must be an IP address rather than a DNS host name. 671If 672.Ar portnum 673is not specified, the destination port number is not changed. 674.Pp 675The 676.Ar server 677specification is mandatory unless the 678.Cm delete 679command is being used. 680.It Cm rule Ar index 681Normally, each call to 682.Fn LibAliasProxyRule 683inserts the next rule at the start of a linear list of rules. 684If an 685.Ar index 686is specified, the new rule will be checked after all rules with lower 687indices. 688Calls to 689.Fn LibAliasProxyRule 690that do not specify a rule are assigned rule 0. 691.It Cm delete Ar index 692This token and its argument MUST NOT be used with any other tokens. 693When used, all existing rules with the given 694.Ar index 695are deleted. 696.It Cm proto tcp | udp 697If specified, only packets of the given protocol type are matched. 698.It Cm src Ar IP Ns Op / Ns Ar bits 699If specified, only packets with a source address matching the given 700.Ar IP 701are matched. 702If 703.Ar bits 704is also specified, then the first 705.Ar bits 706bits of 707.Ar IP 708are taken as a network specification, and all IP addresses from that 709network will be matched. 710.It Cm dst Ar IP Ns Op / Ns Ar bits 711If specified, only packets with a destination address matching the given 712.Ar IP 713are matched. 714If 715.Ar bits 716is also specified, then the first 717.Ar bits 718bits of 719.Ar IP 720are taken as a network specification, and all IP addresses from that 721network will be matched. 722.El 723.Pp 724This function is usually used to redirect outgoing connections for 725internal machines that are not permitted certain types of internet 726access, or to restrict access to certain external machines. 727.Ed 728.Pp 729.Ft struct alias_link * 730.Fo LibAliasRedirectProto 731.Fa "struct libalias *" 732.Fa "struct in_addr local_addr" 733.Fa "struct in_addr remote_addr" 734.Fa "struct in_addr alias_addr" 735.Fa "u_char proto" 736.Fc 737.Bd -ragged -offset indent 738This function specifies that any IP packet with protocol number of 739.Fa proto 740from a given remote address to an alias address will be 741redirected to a specified local address. 742.Pp 743If 744.Fa local_addr 745or 746.Fa alias_addr 747is zero, this indicates that the packet aliasing address as established 748by 749.Fn LibAliasSetAddress 750is to be used. 751Even if 752.Fn LibAliasSetAddress 753is called to change the address after 754.Fn LibAliasRedirectProto 755is called, a zero reference will track this change. 756.Pp 757If 758.Fa remote_addr 759is zero, this indicates to redirect packets from any remote address. 760Non-zero remote addresses can sometimes be useful for firewalling. 761.Pp 762If two calls to 763.Fn LibAliasRedirectProto 764overlap in their address specifications, then the most recent call 765will have precedence. 766.Pp 767This function returns a pointer which can subsequently be used by 768.Fn LibAliasRedirectDelete . 769If 770.Dv NULL 771is returned, then the function call did not complete successfully. 772.Ed 773.Sh FRAGMENT HANDLING 774The functions in this section are used to deal with incoming fragments. 775.Pp 776Outgoing fragments are handled within 777.Fn LibAliasOut 778by changing the address according to any applicable mapping set by 779.Fn LibAliasRedirectAddr , 780or the default aliasing address set by 781.Fn LibAliasSetAddress . 782.Pp 783Incoming fragments are handled in one of two ways. 784If the header of a fragmented IP packet has already been seen, then all 785subsequent fragments will be re-mapped in the same manner the header 786fragment was. 787Fragments which arrive before the header are saved and then retrieved 788once the header fragment has been resolved. 789.Pp 790.Ft int 791.Fn LibAliasSaveFragment "struct libalias *" "void *ptr" 792.Bd -ragged -offset indent 793When 794.Fn LibAliasIn 795returns 796.Dv PKT_ALIAS_UNRESOLVED_FRAGMENT , 797this function can be used to save the pointer to the unresolved fragment. 798.Pp 799It is implicitly assumed that 800.Fa ptr 801points to a block of memory allocated by 802.Xr malloc 3 . 803If the fragment is never resolved, the packet aliasing engine will 804automatically free the memory after a timeout period. 805[Eventually this function should be modified so that a callback function 806for freeing memory is passed as an argument.] 807.Pp 808This function returns 809.Dv PKT_ALIAS_OK 810if it was successful and 811.Dv PKT_ALIAS_ERROR 812if there was an error. 813.Ed 814.Pp 815.Ft void * 816.Fn LibAliasGetFragment "struct libalias *" "void *buffer" 817.Bd -ragged -offset indent 818This function can be used to retrieve fragment pointers saved by 819.Fn LibAliasSaveFragment . 820The IP header fragment pointed to by 821.Fa buffer 822is the header fragment indicated when 823.Fn LibAliasIn 824returns 825.Dv PKT_ALIAS_FOUND_HEADER_FRAGMENT . 826Once a fragment pointer is retrieved, it becomes the calling program's 827responsibility to free the dynamically allocated memory for the fragment. 828.Pp 829The 830.Fn LibAliasGetFragment 831function can be called sequentially until there are no more fragments 832available, at which time it returns 833.Dv NULL . 834.Ed 835.Pp 836.Ft void 837.Fn LibAliasFragmentIn "struct libalias *" "void *header" "void *fragment" 838.Bd -ragged -offset indent 839When a fragment is retrieved with 840.Fn LibAliasGetFragment , 841it can then be de-aliased with a call to 842.Fn LibAliasFragmentIn . 843The 844.Fa header 845argument is the pointer to a header fragment used as a template, and 846.Fa fragment 847is the pointer to the packet to be de-aliased. 848.Ed 849.Sh MISCELLANEOUS FUNCTIONS 850.Ft struct alias_link * 851.Fn AddLink "struct libalias *" "struct in_addr src_addr" "struct in_addr dst_addr" \ 852"struct in_addr alias_addr" "u_short src_port" "u_short dst_port" \ 853"int alias_param" "int link_type" 854.Bd -ragged -offset indent 855This function adds new state to the instance hash table. 856The dst_address and/or dst_port may be given as zero, which 857introduces some dynamic character into the link, since 858LibAliasSetAddress can change the address that is used. 859However, in the current implementation, such links can only be used 860for inbound (ext -> int) traffic. 861.Ed 862.Pp 863.Ft void 864.Fn LibAliasSetTarget "struct libalias *" "struct in_addr addr" 865.Bd -ragged -offset indent 866When an incoming packet not associated with any pre-existing aliasing link 867arrives at the host machine, it will be sent to the address indicated by a 868call to 869.Fn LibAliasSetTarget . 870.Pp 871If this function is called with an 872.Dv INADDR_NONE 873address argument, then all new incoming packets go to the address set by 874.Fn LibAliasSetAddress . 875.Pp 876If this function is not called, or is called with an 877.Dv INADDR_ANY 878address argument, then all new incoming packets go to the address specified 879in the packet. 880This allows external machines to talk directly to internal machines if they 881can route packets to the machine in question. 882.Ed 883.Pp 884.Ft u_short 885.Fn LibAliasInternetChecksum "struct libalias *" "u_short *buffer" "int nbytes" 886.Bd -ragged -offset indent 887This is a utility function that does not seem to be available elsewhere and 888is included as a convenience. 889It computes the internet checksum, which is used in both IP and 890protocol-specific headers (TCP, UDP, ICMP). 891.Pp 892The 893.Fa buffer 894argument points to the data block to be checksummed, and 895.Fa nbytes 896is the number of bytes. 897The 16-bit checksum field should be zeroed before computing the checksum. 898.Pp 899Checksums can also be verified by operating on a block of data including 900its checksum. 901If the checksum is valid, 902.Fn LibAliasInternetChecksum 903will return zero. 904.Ed 905.Pp 906.Ft int 907.Fn LibAliasUnaliasOut "struct libalias *" "void *buffer" "int maxpacketsize" 908.Bd -ragged -offset indent 909An outgoing packet, which has already been aliased, 910has its private address/port information restored by this function. 911The IP packet is pointed to by 912.Fa buffer , 913and 914.Fa maxpacketsize 915is provided for error checking purposes. 916This function can be used if an already-aliased packet needs to have its 917original IP header restored for further processing (e.g.\& logging). 918.Ed 919.Sh CONCEPTUAL BACKGROUND 920This section is intended for those who are planning to modify the source 921code or want to create somewhat esoteric applications using the packet 922aliasing functions. 923.Pp 924The conceptual framework under which the packet aliasing engine operates 925is described here. 926Central to the discussion is the idea of an 927.Em aliasing link 928which describes the relationship for a given packet transaction between 929the local machine, aliased identity and remote machine. 930It is discussed how such links come into existence and are destroyed. 931.Ss ALIASING LINKS 932There is a notion of an 933.Em aliasing link , 934which is a 7-tuple describing a specific translation: 935.Bd -literal -offset indent 936(local addr, local port, alias addr, alias port, 937 remote addr, remote port, protocol) 938.Ed 939.Pp 940Outgoing packets have the local address and port number replaced with the 941alias address and port number. 942Incoming packets undergo the reverse process. 943The packet aliasing engine attempts to match packets against an internal 944table of aliasing links to determine how to modify a given IP packet. 945Both the IP header and protocol dependent headers are modified as necessary. 946Aliasing links are created and deleted as necessary according to network 947traffic. 948.Pp 949Protocols can be TCP, UDP or even ICMP in certain circumstances. 950(Some types of ICMP packets can be aliased according to sequence or ID 951number which acts as an equivalent port number for identifying how 952individual packets should be handled.) 953.Pp 954Each aliasing link must have a unique combination of the following five 955quantities: alias address/port, remote address/port and protocol. 956This ensures that several machines on a local network can share the 957same aliasing IP address. 958In cases where conflicts might arise, the aliasing port is chosen so that 959uniqueness is maintained. 960.Ss STATIC AND DYNAMIC LINKS 961Aliasing links can either be static or dynamic. 962Static links persist indefinitely and represent fixed rules for translating 963IP packets. 964Dynamic links come into existence for a specific TCP connection or UDP 965transaction or ICMP ECHO sequence. 966For the case of TCP, the connection can be monitored to see when the 967associated aliasing link should be deleted. 968Aliasing links for UDP transactions (and ICMP ECHO and TIMESTAMP requests) 969work on a simple timeout rule. 970When no activity is observed on a dynamic link for a certain amount of time 971it is automatically deleted. 972Timeout rules also apply to TCP connections which do not open or close 973properly. 974.Ss PARTIALLY SPECIFIED ALIASING LINKS 975Aliasing links can be partially specified, meaning that the remote address 976and/or remote port are unknown. 977In this case, when a packet matching the incomplete specification is found, 978a fully specified dynamic link is created. 979If the original partially specified link is dynamic, it will be deleted 980after the fully specified link is created, otherwise it will persist. 981.Pp 982For instance, a partially specified link might be 983.Bd -literal -offset indent 984(192.168.0.4, 23, 204.228.203.215, 8066, 0, 0, tcp) 985.Ed 986.Pp 987The zeros denote unspecified components for the remote address and port. 988If this link were static it would have the effect of redirecting all 989incoming traffic from port 8066 of 204.228.203.215 to port 23 (telnet) 990of machine 192.168.0.4 on the local network. 991Each individual telnet connection would initiate the creation of a distinct 992dynamic link. 993.Ss DYNAMIC LINK CREATION 994In addition to aliasing links, there are also address mappings that can be 995stored within the internal data table of the packet aliasing mechanism. 996.Bd -literal -offset indent 997(local addr, alias addr) 998.Ed 999.Pp 1000Address mappings are searched when creating new dynamic links. 1001.Pp 1002All outgoing packets from the local network automatically create a dynamic 1003link if they do not match an already existing fully specified link. 1004If an address mapping exists for the outgoing packet, this determines 1005the alias address to be used. 1006If no mapping exists, then a default address, usually the address of the 1007packet aliasing host, is used. 1008If necessary, this default address can be changed as often as each individual 1009packet arrives. 1010.Pp 1011The aliasing port number is determined such that the new dynamic link does 1012not conflict with any existing links. 1013In the default operating mode, the packet aliasing engine attempts to set 1014the aliasing port equal to the local port number. 1015If this results in a conflict, then port numbers are randomly chosen until 1016a unique aliasing link can be established. 1017In an alternate operating mode, the first choice of an aliasing port is also 1018random and unrelated to the local port number. 1019.Sh MODULAR ARCHITECTURE Po AND Xr ipfw 4 SUPPORT Pc 1020One of the latest improvements to 1021.Nm 1022was to make its support 1023for new protocols independent from the rest of the library, giving it 1024the ability to load/unload support for new protocols at run-time. 1025To achieve this feature, all the code for protocol handling was moved 1026to a series of modules outside of the main library. 1027These modules are compiled from the same sources but work in 1028different ways, depending on whether they are compiled to work inside a kernel 1029or as part of the userland library. 1030.Ss LIBALIAS MODULES IN KERNEL LAND 1031When compiled for the kernel, 1032.Nm 1033modules are plain KLDs recognizable with the 1034.Pa alias_ 1035prefix. 1036.Pp 1037To add support for a new protocol, load the corresponding module. 1038For example: 1039.Pp 1040.Dl "kldload alias_ftp" 1041.Pp 1042When support for a protocol is no longer needed, its module can be unloaded: 1043.Pp 1044.Dl "kldunload alias_ftp" 1045.Ss LIBALIAS MODULES IN USERLAND 1046Due to the differences between kernel and userland (no KLD mechanism, 1047many different address spaces, etc.), we had to change a bit how to 1048handle module loading/tracking/unloading in userland. 1049.Pp 1050While compiled for a userland 1051.Nm , 1052all the modules are plain libraries, residing in 1053.Pa /usr/lib , 1054and recognizable with the 1055.Pa libalias_ 1056prefix. 1057.Pp 1058There is a configuration file, 1059.Pa /etc/libalias.conf , 1060with the following contents (by default): 1061.Bd -literal -offset indent 1062/usr/lib/libalias_ftp.so 1063/usr/lib/libalias_irc.so 1064/usr/lib/libalias_nbt.so 1065/usr/lib/libalias_pptp.so 1066/usr/lib/libalias_skinny.so 1067/usr/lib/libalias_smedia.so 1068.Ed 1069.Pp 1070This file contains the paths to the modules that 1071.Nm 1072will load. 1073To load/unload a new module, just add its path to 1074.Pa libalias.conf 1075and call 1076.Fn LibAliasRefreshModules 1077from the program. 1078In case the application provides a 1079.Dv SIGHUP 1080signal handler, add a call to 1081.Fn LibAliasRefreshModules 1082inside the handler, and every time you want to refresh the loaded modules, 1083send it the 1084.Dv SIGHUP 1085signal: 1086.Pp 1087.Dl "kill -HUP <process_pid>" 1088.Ss MODULAR ARCHITECURE: HOW IT WORKS 1089The modular architecture of 1090.Nm 1091works similar whether it is running inside the 1092kernel or in userland. 1093From 1094.Pa alias_mod.c : 1095.Bd -literal 1096/* Protocol and userland module handlers chains. */ 1097LIST_HEAD(handler_chain, proto_handler) handler_chain ... 1098\&... 1099SLIST_HEAD(dll_chain, dll) dll_chain ... 1100.Ed 1101.Pp 1102.Va handler_chain 1103keeps track of all the protocol handlers loaded, while 1104.Va ddl_chain 1105tracks which userland modules are loaded. 1106.Pp 1107.Va handler_chain 1108is composed of 1109.Vt "struct proto_handler" 1110entries: 1111.Bd -literal 1112struct proto_handler { 1113 u_int pri; 1114 int16_t dir; 1115 uint8_t proto; 1116 int (*fingerprint)(struct libalias *la, 1117 struct ip *pip, struct alias_data *ah); 1118 int (*protohandler)(struct libalias *la, 1119 struct ip *pip, struct alias_data *ah); 1120 TAILQ_ENTRY(proto_handler) link; 1121}; 1122.Ed 1123.Pp 1124where: 1125.Bl -inset 1126.It Va pri 1127is the priority assigned to a protocol handler; lower priority 1128is better. 1129.It Va dir 1130is the direction of packets: ingoing or outgoing. 1131.It Va proto 1132indicates to which protocol this packet belongs: IP, TCP or UDP. 1133.It Va fingerprint 1134points to the fingerprint function while protohandler points 1135to the protocol handler function. 1136.El 1137.Pp 1138The 1139.Va fingerprint 1140function has the dual role of checking if the 1141incoming packet is found, and if it belongs to any categories that this 1142module can handle. 1143.Pp 1144The 1145.Va protohandler 1146function actually manipulates 1147the packet to make 1148.Nm 1149correctly NAT it. 1150.Pp 1151When a packet enters 1152.Nm , 1153if it meets a module hook, 1154.Va handler_chain 1155is searched to see if there is an handler that matches 1156this type of a packet (it checks protocol and direction of packet). 1157Then, if more than one handler is found, it starts with the module with 1158the lowest priority number: it calls the 1159.Va fingerprint 1160function and interprets the result. 1161.Pp 1162If the result value is equal to 0 then it calls the protocol handler 1163of this handler and returns. 1164Otherwise, it proceeds to the next eligible module until the 1165.Va handler_chain 1166is exhausted. 1167.Pp 1168Inside 1169.Nm , 1170the module hook looks like this: 1171.Bd -literal -offset indent 1172struct alias_data ad = { 1173 lnk, 1174 &original_address, 1175 &alias_address, 1176 &alias_port, 1177 &ud->uh_sport, /* original source port */ 1178 &ud->uh_dport, /* original dest port */ 1179 256 /* maxpacketsize */ 1180}; 1181 1182\&... 1183 1184/* walk out chain */ 1185err = find_handler(IN, UDP, la, pip, &ad); 1186.Ed 1187.Pp 1188All data useful to a module are gathered together in an 1189.Vt alias_data 1190structure, then 1191.Fn find_handler 1192is called. 1193The 1194.Fn find_handler 1195function is responsible for walking the handler 1196chain; it receives as input parameters: 1197.Bl -tag -width indent 1198.It Fa IN 1199direction 1200.It Fa UDP 1201working protocol 1202.It Fa la 1203pointer to this instance of libalias 1204.It Fa pip 1205pointer to a 1206.Vt "struct ip" 1207.It Fa ad 1208pointer to 1209.Vt "struct alias_data" 1210(see above) 1211.El 1212.Pp 1213In this case, 1214.Fn find_handler 1215will search only for modules registered for 1216supporting INcoming UDP packets. 1217.Pp 1218As was mentioned earlier, 1219.Nm 1220in userland is a bit different, as 1221care must be taken in module handling as well (avoiding duplicate load of 1222modules, avoiding modules with same name, etc.) so 1223.Va dll_chain 1224was introduced. 1225.Pp 1226.Va dll_chain 1227contains a list of all userland 1228.Nm 1229modules loaded. 1230.Pp 1231When an application calls 1232.Fn LibAliasRefreshModules , 1233.Nm 1234first unloads all the loaded modules, then reloads all the modules listed in 1235.Pa /etc/libalias.conf : 1236for every module loaded, a new entry is added to 1237.Va dll_chain . 1238.Pp 1239.Va dll_chain 1240is composed of 1241.Vt "struct dll" 1242entries: 1243.Bd -literal 1244struct dll { 1245 /* name of module */ 1246 char name[DLL_LEN]; 1247 /* 1248 * ptr to shared obj obtained through 1249 * dlopen() - use this ptr to get access 1250 * to any symbols from a loaded module 1251 * via dlsym() 1252 */ 1253 void *handle; 1254 struct dll *next; 1255}; 1256.Ed 1257.Bl -inset 1258.It Va name 1259is the name of the module. 1260.It Va handle 1261is a pointer to the module obtained through 1262.Xr dlopen 3 . 1263.El 1264Whenever a module is loaded in userland, an entry is added to 1265.Va dll_chain , 1266then every protocol handler present in that module 1267is resolved and registered in 1268.Va handler_chain . 1269.Ss HOW TO WRITE A MODULE FOR LIBALIAS 1270There is a module (called 1271.Pa alias_dummy.[ch] ) 1272in 1273.Nm 1274that can be used as a skeleton for future work. 1275Here we analyse some parts of that module. 1276From 1277.Pa alias_dummy.c : 1278.Bd -literal 1279struct proto_handler handlers[] = { 1280 { 1281 .pri = 666, 1282 .dir = IN|OUT, 1283 .proto = UDP|TCP, 1284 .fingerprint = fingerprint, 1285 .protohandler= protohandler, 1286 }, 1287 { EOH } 1288}; 1289.Ed 1290.Pp 1291The variable 1292.Va handlers 1293is the 1294.Dq "most important thing" 1295in a module 1296since it describes the handlers present and lets the outside world use 1297it in an opaque way. 1298.Pp 1299It must ALWAYS be present in every module, and it MUST retain 1300the name 1301.Va handlers , 1302otherwise attempting to load a module in userland will fail and 1303complain about missing symbols: for more information about module 1304load/unload, please refer to 1305.Fn LibAliasRefreshModules , 1306.Fn LibAliasLoadModule 1307and 1308.Fn LibAliasUnloadModule 1309in 1310.Pa alias.c . 1311.Pp 1312.Va handlers 1313contains all the 1314.Vt proto_handler 1315structures present in a module. 1316.Bd -literal 1317static int 1318mod_handler(module_t mod, int type, void *data) 1319{ 1320 int error; 1321 1322 switch (type) { 1323 case MOD_LOAD: 1324 error = LibAliasAttachHandlers(handlers); 1325 break; 1326 case MOD_UNLOAD: 1327 error = LibAliasDetachHandlers(handlers); 1328 break; 1329 default: 1330 error = EINVAL; 1331 } 1332 return (error); 1333} 1334.Ed 1335When running as KLD, 1336.Fn mod_handler 1337registers/deregisters the module using 1338.Fn LibAliasAttachHandlers 1339and 1340.Fn LibAliasDetachHandlers , 1341respectively. 1342.Pp 1343Every module must contain at least 2 functions: one fingerprint 1344function and a protocol handler function. 1345.Bd -literal 1346#ifdef _KERNEL 1347static 1348#endif 1349int 1350fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) 1351{ 1352 1353\&... 1354} 1355 1356#ifdef _KERNEL 1357static 1358#endif 1359int 1360protohandler(struct libalias *la, struct ip *pip, 1361 struct alias_data *ah) 1362{ 1363 1364\&... 1365} 1366.Ed 1367and they must accept exactly these input parameters. 1368.Ss PATCHING AN APPLICATION FOR USERLAND LIBALIAS MODULES 1369To add module support into an application that uses 1370.Nm , 1371the following simple steps can be followed. 1372.Bl -enum 1373.It 1374Find the main file of an application 1375(let us call it 1376.Pa main.c ) . 1377.It 1378Add this to the header section of 1379.Pa main.c , 1380if not already present: 1381.Pp 1382.Dl "#include <signal.h>" 1383.Pp 1384and this just after the header section: 1385.Pp 1386.Dl "static void signal_handler(int);" 1387.It 1388Add the following line to the init function of an application or, 1389if it does not have any init function, put it in 1390.Fn main : 1391.Pp 1392.Dl "signal(SIGHUP, signal_handler);" 1393.Pp 1394and place the 1395.Fn signal_handler 1396function somewhere in 1397.Pa main.c : 1398.Bd -literal -offset indent 1399static void 1400signal_handler(int sig) 1401{ 1402 1403 LibAliasRefreshModules(); 1404} 1405.Ed 1406.Pp 1407Otherwise, if an application already traps the 1408.Dv SIGHUP 1409signal, just add a call to 1410.Fn LibAliasRefreshModules 1411in the signal handler function. 1412.El 1413For example, to patch 1414.Xr natd 8 1415to use 1416.Nm 1417modules, just add the following line to 1418.Fn RefreshAddr "int sig __unused" : 1419.Pp 1420.Dl "LibAliasRefreshModules()" 1421.Pp 1422recompile and you are done. 1423.Ss LOGGING SUPPORT IN KERNEL LAND 1424When working as KLD, 1425.Nm 1426now has log support that 1427happens on a buffer allocated inside 1428.Vt "struct libalias" 1429(from 1430.Pa alias_local.h ) : 1431.Bd -literal 1432struct libalias { 1433 ... 1434 1435 /* log descriptor */ 1436#ifdef KERNEL_LOG 1437 char *logDesc; /* 1438 * ptr to an auto-malloced 1439 * memory buffer when libalias 1440 * works as kld 1441 */ 1442#else 1443 FILE *logDesc; /* 1444 * ptr to /var/log/alias.log 1445 * when libalias runs as a 1446 * userland lib 1447 */ 1448#endif 1449 1450 ... 1451} 1452.Ed 1453so all applications using 1454.Nm 1455will be able to handle their 1456own logs, if they want, accessing 1457.Va logDesc . 1458Moreover, every change to a log buffer is automatically added to 1459.Xr syslog 3 1460with the 1461.Dv LOG_SECURITY 1462facility and the 1463.Dv LOG_INFO 1464level. 1465.Sh AUTHORS 1466.An Charles Mott Aq cm@linktel.net , 1467versions 1.0 - 1.8, 2.0 - 2.4. 1468.An Eivind Eklund Aq eivind@FreeBSD.org , 1469versions 1.8b, 1.9 and 2.5. 1470Added IRC DCC support as well as contributing a number of architectural 1471improvements; added the firewall bypass for FTP/IRC DCC. 1472.An Erik Salander Aq erik@whistle.com 1473added support for PPTP and RTSP. 1474.An Junichi Satoh Aq junichi@junichi.org 1475added support for RTSP/PNA. 1476.An Ruslan Ermilov Aq ru@FreeBSD.org 1477added support for PPTP and LSNAT as well as general hacking. 1478.An Gleb Smirnoff Aq glebius@FreeBSD.org 1479ported the library to kernel space. 1480.An Paolo Pisati Aq piso@FreeBSD.org 1481made the library modular, moving support for all 1482protocols (except for IP, TCP and UDP) to external modules. 1483.Sh ACKNOWLEDGEMENTS 1484Listed below, in approximate chronological order, are individuals who 1485have provided valuable comments and/or debugging assistance. 1486.Bd -ragged -offset indent 1487.An -split 1488.An Gary Roberts 1489.An Tom Torrance 1490.An Reto Burkhalter 1491.An Martin Renters 1492.An Brian Somers 1493.An Paul Traina 1494.An Ari Suutari 1495.An Dave Remien 1496.An J. Fortes 1497.An Andrzej Bialecki 1498.An Gordon Burditt 1499.Ed 1500