xref: /freebsd/sys/netinet/libalias/libalias.3 (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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