2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * natd - Network Address Translation Daemon for FreeBSD.
25 * This software is provided free of charge, with no
26 * warranty of any kind, either expressed or implied.
27 * Use at your own risk.
29 * You may copy, modify and distribute this software (natd.c) freely.
31 * Ari Suutari <suutari@iki.fi>
34 * $FreeBSD: src/sbin/natd/natd.c,v 1.25.2.3 2000/07/11 20:00:57 ru Exp $
39 #include <sys/types.h>
40 #include <sys/socket.h>
43 #include <sys/sysctl.h>
46 #include <netinet/in.h>
47 #include <netinet/in_systm.h>
48 #include <netinet/ip.h>
49 #include <netinet/tcp.h>
50 #include <netinet/udp.h>
51 #include <netinet/ip_icmp.h>
53 #include <net/if_dl.h>
54 #include <net/route.h>
55 #include <arpa/inet.h>
71 #include <mach/mach_time.h>
72 #include <mach/clock_types.h>
77 * Default values for input and output
78 * divert socket ports.
81 #define DEFAULT_SERVICE "natd"
84 * Definition of a port range, and macros to deal with values.
85 * FORMAT: HI 16-bits == first port in range, 0 == all ports.
86 * LO 16-bits == number of ports in range
87 * NOTES: - Port values are not stored in network byte order.
90 typedef uint32_t port_range
;
92 #define GETLOPORT(x) ((x) >> 0x10)
93 #define GETNUMPORTS(x) ((x) & 0x0000ffff)
94 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
96 /* Set y to be the low-port value in port_range variable x. */
97 #define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
99 /* Set y to be the number of ports in port_range variable x. */
100 #define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
103 * Function prototypes.
106 static void DoAliasing (int fd
, int direction
);
107 static void DaemonMode (void);
108 static void HandleRoutingInfo (int fd
);
109 static void Usage (void);
110 static char* FormatPacket (struct ip
*);
111 static void PrintPacket (struct ip
*);
112 static void SyslogPacket (struct ip
*, int priority
, const char *label
);
113 static void SetAliasAddressFromIfName (const char *ifName
);
114 static void InitiateShutdown (int);
115 static void Shutdown (int);
116 static void RefreshAddr (int);
117 static void HandleInfo (int);
118 static void ParseOption (const char* option
, const char* parms
);
119 static void ReadConfigFile (const char* fileName
);
120 static void SetupPortRedirect (const char* parms
);
121 static void SetupProtoRedirect(const char* parms
);
122 static void SetupAddressRedirect (const char* parms
);
123 static void StrToAddr (const char* str
, struct in_addr
* addr
);
124 static u_short
StrToPort (const char* str
, const char* proto
);
125 static int StrToPortRange (const char* str
, const char* proto
, port_range
*portRange
);
126 static int StrToProto (const char* str
);
127 static int StrToAddrAndPortRange (const char* str
, struct in_addr
* addr
, char* proto
, port_range
*portRange
);
128 static void ParseArgs (int argc
, char** argv
);
129 static void FlushPacketBuffer (int fd
);
130 static void DiscardIncomingPackets (int fd
);
131 static void SetupPunchFW(const char *strValue
);
138 static int background
;
140 static int assignAliasAddr
;
143 static u_short inPort
;
144 static u_short outPort
;
145 static u_short inOutPort
;
146 static struct in_addr aliasAddr
;
147 static int dynamicMode
;
150 static int aliasOverhead
;
152 static char packetBuf
[IP_MAXPACKET
];
153 static int packetLen
;
154 static struct sockaddr_in packetAddr
;
155 static int packetSock
;
156 static int packetDirection
;
157 static int dropIgnoredIncoming
;
158 static int logDropped
;
159 static int logFacility
;
167 * Note: more details on NAT-PMP can be found at :
168 * <http://files.dns-sd.org/draft-cheshire-nat-pmp.txt>
171 #define NATPMP_ANNOUNCEMENT_PORT 5350
172 #define NATPMP_PORT 5351
174 #define NATPMVERSION 0
175 #define PUBLICADDRREQ 0
178 #define MAPUDPTCPREQ 3
179 #define SERVERREPLYOP 128
182 #define NOTSUPPORTEDVERSION 1
183 #define NOTAUTHORIZED 2
184 #define NETWORKFAILURE 3
185 #define OUTOFRESOURCES 4
186 #define UNSUPPORTEDOPCODE 5
189 #define TIMER_RATE 250000
193 typedef struct stdportmaprequest
{
198 typedef struct publicportreq
{
202 uint16_t privateport
;
204 uint32_t lifetime
; /* in seconds */
207 typedef struct publicaddrreply
{
215 typedef struct publicportreply
{
220 uint16_t privateport
;
222 uint32_t lifetime
; /* in seconds */
225 typedef struct stderrreply
{
233 static int enable_natportmap
= 0;
234 static struct in_addr lastassignaliasAddr
;
235 static int portmapSock
= -1;
236 static struct in_addr
*forwardedinterfaceaddr
;
237 static char **forwardedinterfacename
;
238 static int numofinterfaces
= 0; /* has to be at least one */
239 static int numoftries
=MAXRETRY
;
240 static struct itimerval itval
;
241 static int Natdtimerset
= 0;
242 static double secdivisor
;
245 static void HandlePortMap( int fd
);
246 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
);
247 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
);
248 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*reply
, u_short publicport
, int result
);
249 static void Doubletime( struct timeval
*tvp
);
250 static void Stoptimer();
251 static void Natdtimer();
252 static void SendPortMapMulti( );
253 static void NotifyPublicAddress();
254 static void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
);
255 static void NatPortMapPInit();
257 extern int FindAliasPortOut(struct in_addr src_addr
, struct in_addr dst_addr
, u_short src_port
, u_short pub_port
, u_char proto
, int lifetime
, char addmapping
);
259 #endif /* NATPORTMAP */
261 int main (int argc
, char** argv
)
267 struct sockaddr_in addr
;
273 * Initialize packet aliasing software.
274 * Done already here to be able to alter option bits
275 * during command line and configuration file processing.
290 aliasAddr
.s_addr
= INADDR_NONE
;
292 lastassignaliasAddr
.s_addr
= INADDR_NONE
;
297 logFacility
= LOG_DAEMON
;
299 * Mark packet buffer empty.
302 packetDirection
= DONT_KNOW
;
304 ParseArgs (argc
, argv
);
306 * Open syslog channel.
308 openlog ("natd", LOG_CONS
| LOG_PID
| (verbose
? LOG_PERROR
: 0),
311 * Check that valid aliasing address has been given.
313 if (aliasAddr
.s_addr
== INADDR_NONE
&& ifName
== NULL
)
314 errx (1, "aliasing address not given");
317 * Check that valid port number is known.
319 if (inPort
!= 0 || outPort
!= 0)
320 if (inPort
== 0 || outPort
== 0)
321 errx (1, "both input and output ports are required");
323 if (inPort
== 0 && outPort
== 0 && inOutPort
== 0)
324 ParseOption ("port", DEFAULT_SERVICE
);
327 * Check if ignored packets should be dropped.
329 dropIgnoredIncoming
= PacketAliasSetMode (0, 0);
330 dropIgnoredIncoming
&= PKT_ALIAS_DENY_INCOMING
;
332 * Create divert sockets. Use only one socket if -p was specified
333 * on command line. Otherwise, create separate sockets for
334 * outgoing and incoming connnections.
338 divertInOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
339 if (divertInOut
== -1)
340 Quit ("Unable to create divert socket.");
348 addr
.sin_family
= AF_INET
;
349 addr
.sin_addr
.s_addr
= INADDR_ANY
;
350 addr
.sin_port
= inOutPort
;
352 if (bind (divertInOut
,
353 (struct sockaddr
*) &addr
,
355 Quit ("Unable to bind divert socket.");
359 divertIn
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
361 Quit ("Unable to create incoming divert socket.");
363 divertOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
365 Quit ("Unable to create outgoing divert socket.");
370 * Bind divert sockets.
373 addr
.sin_family
= AF_INET
;
374 addr
.sin_addr
.s_addr
= INADDR_ANY
;
375 addr
.sin_port
= inPort
;
378 (struct sockaddr
*) &addr
,
380 Quit ("Unable to bind incoming divert socket.");
382 addr
.sin_family
= AF_INET
;
383 addr
.sin_addr
.s_addr
= INADDR_ANY
;
384 addr
.sin_port
= outPort
;
387 (struct sockaddr
*) &addr
,
389 Quit ("Unable to bind outgoing divert socket.");
392 * Create routing socket if interface name specified and in dynamic mode.
398 routeSock
= socket (PF_ROUTE
, SOCK_RAW
, 0);
400 Quit ("Unable to create routing info socket.");
405 SetAliasAddressFromIfName (ifName
);
409 * Create socket for sending ICMP messages.
411 icmpSock
= socket (AF_INET
, SOCK_RAW
, IPPROTO_ICMP
);
413 Quit ("Unable to create ICMP socket.");
415 if ((fdFlags
= fcntl(icmpSock
, F_GETFL
, 0)) == -1)
416 Quit ("fcntl F_GETFL ICMP socket.");
417 fdFlags
|= O_NONBLOCK
;
418 if (fcntl(icmpSock
, F_SETFL
, fdFlags
) == -1)
419 Quit ("fcntl F_SETFL ICMP socket.");
422 if ( enable_natportmap
)
424 /* create socket to listen for port mapping */
425 portmapSock
= socket( AF_INET
, SOCK_DGRAM
, 0);
426 if ( portmapSock
!= -1 )
428 addr
.sin_family
= AF_INET
;
429 addr
.sin_addr
.s_addr
= INADDR_ANY
;
430 addr
.sin_port
= htons(NATPMP_PORT
);
432 if (bind ( portmapSock
,
433 (struct sockaddr
*) &addr
,
435 printf("Binding to NATPM port failed!\n");
437 /* NATPORTMAPP initial set up */
440 if ( !Natdtimerset
){
442 signal(SIGALRM
, Natdtimer
);
445 #endif /* NATPORTMAP */
448 * Become a daemon unless verbose mode was requested.
453 * Catch signals to manage shutdown and
454 * refresh of interface address.
456 siginterrupt(SIGTERM
, 1);
457 siginterrupt(SIGHUP
, 1);
458 signal (SIGTERM
, InitiateShutdown
);
459 signal (SIGHUP
, RefreshAddr
);
460 signal (SIGINFO
, HandleInfo
);
462 * Set alias address if it has been given.
464 if (aliasAddr
.s_addr
!= INADDR_NONE
)
466 PacketAliasSetAddress (aliasAddr
);
468 if ( (enable_natportmap
) && (aliasAddr
.s_addr
!= lastassignaliasAddr
.s_addr
) ){
469 lastassignaliasAddr
.s_addr
= aliasAddr
.s_addr
;
470 NotifyPublicAddress();
475 * We need largest descriptor number for select.
480 if (divertIn
> fdMax
)
483 if (divertOut
> fdMax
)
486 if (divertInOut
> fdMax
)
489 if (routeSock
> fdMax
)
492 if (icmpSock
> fdMax
)
496 if ( portmapSock
> fdMax
)
503 if (divertInOut
!= -1 && !ifName
&& packetSock
== -1) {
505 * When using only one socket, just call
506 * DoAliasing repeatedly to process packets.
508 DoAliasing (divertInOut
, DONT_KNOW
);
512 * Build read mask from socket descriptors to select.
515 FD_ZERO (&writeMask
);
518 * If there is unsent packet in buffer, use select
519 * to check when socket comes writable again.
521 if (packetSock
!= -1) {
523 FD_SET (packetSock
, &writeMask
);
527 * No unsent packet exists - safe to check if
528 * new ones are available.
531 FD_SET (divertIn
, &readMask
);
534 FD_SET (divertOut
, &readMask
);
536 if (divertInOut
!= -1)
537 FD_SET (divertInOut
, &readMask
);
540 FD_SET(icmpSock
, &readMask
);
543 * Routing info is processed always.
546 FD_SET (routeSock
, &readMask
);
548 if ( portmapSock
!= -1 )
549 FD_SET (portmapSock
, &readMask
);
551 if (select (fdMax
+ 1,
557 if (errno
== EINTR
) {
564 Quit ("Select failed.");
567 if (packetSock
!= -1)
568 if (FD_ISSET (packetSock
, &writeMask
))
569 FlushPacketBuffer (packetSock
);
572 if (FD_ISSET (divertIn
, &readMask
))
573 DoAliasing (divertIn
, INPUT
);
576 if (FD_ISSET (divertOut
, &readMask
))
577 DoAliasing (divertOut
, OUTPUT
);
579 if (divertInOut
!= -1)
580 if (FD_ISSET (divertInOut
, &readMask
))
581 DoAliasing (divertInOut
, DONT_KNOW
);
584 if (FD_ISSET (routeSock
, &readMask
))
585 HandleRoutingInfo (routeSock
);
588 if (FD_ISSET (icmpSock
, &readMask
))
589 DiscardIncomingPackets (icmpSock
);
592 if ( portmapSock
!= -1)
593 if (FD_ISSET (portmapSock
, &readMask
))
594 HandlePortMap( portmapSock
);
604 static void DaemonMode ()
611 pidFile
= fopen (PIDFILE
, "w");
614 fprintf (pidFile
, "%d\n", getpid ());
623 fd
= open("/var/run/natd.log", O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
625 if (fd
!= STDOUT_FILENO
) {
626 dup2(fd
, STDOUT_FILENO
);
629 dup2(STDOUT_FILENO
, STDERR_FILENO
);
635 static void ParseArgs (int argc
, char** argv
)
640 int len
; /* bounds checking */
642 for (arg
= 1; arg
< argc
; arg
++) {
647 warnx ("invalid option %s", opt
);
654 while (arg
< argc
- 1) {
656 if (argv
[arg
+ 1][0] == '-')
660 strncat (parmBuf
, " ", sizeof(parmBuf
) - (len
+ 1));
661 len
+= strlen(parmBuf
+ len
);
665 strncat (parmBuf
, argv
[arg
], sizeof(parmBuf
) - (len
+ 1));
666 len
+= strlen(parmBuf
+ len
);
670 ParseOption (opt
+ 1, (len
? parmBuf
: NULL
));
675 static void DoAliasing (int fd
, int direction
)
683 if (assignAliasAddr
) {
685 SetAliasAddressFromIfName (ifName
);
689 * Get packet from socket.
691 addrSize
= sizeof packetAddr
;
692 origBytes
= recvfrom (fd
,
696 (struct sockaddr
*) &packetAddr
,
699 if (origBytes
== -1) {
702 Warn ("read from divert socket failed");
707 * This is a IP packet.
709 ip
= (struct ip
*) packetBuf
;
710 if (direction
== DONT_KNOW
) {
711 if (packetAddr
.sin_addr
.s_addr
== INADDR_ANY
)
719 * Print packet direction and protocol type.
721 printf (direction
== OUTPUT
? "Out " : "In ");
737 printf ("[%d] ", ip
->ip_p
);
746 if (direction
== OUTPUT
) {
748 * Outgoing packets. Do aliasing.
750 PacketAliasOut (packetBuf
, IP_MAXPACKET
);
757 status
= PacketAliasIn (packetBuf
, IP_MAXPACKET
);
758 if (status
== PKT_ALIAS_IGNORED
&&
759 dropIgnoredIncoming
) {
762 printf (" dropped.\n");
765 SyslogPacket (ip
, LOG_WARNING
, "denied");
771 * Length might have changed during aliasing.
773 bytes
= ntohs (ip
->ip_len
);
775 * Update alias overhead size for outgoing packets.
777 if (direction
== OUTPUT
&&
778 bytes
- origBytes
> aliasOverhead
)
779 aliasOverhead
= bytes
- origBytes
;
784 * Print addresses after aliasing.
786 printf (" aliased to\n");
794 packetDirection
= direction
;
796 FlushPacketBuffer (fd
);
799 static void FlushPacketBuffer (int fd
)
804 * Put packet back for processing.
810 (struct sockaddr
*) &packetAddr
,
813 if (wrote
!= packetLen
) {
815 * If buffer space is not available,
816 * just return. Main loop will take care of
817 * retrying send when space becomes available.
819 if (errno
== ENOBUFS
)
822 if (errno
== EMSGSIZE
) {
824 if (packetDirection
== OUTPUT
&&
826 SendNeedFragIcmp (icmpSock
,
827 (struct ip
*) packetBuf
,
828 ifMTU
- aliasOverhead
);
832 sprintf (msgBuf
, "failed to write packet back");
840 static void HandleRoutingInfo (int fd
)
843 struct if_msghdr ifMsg
;
845 * Get packet from socket.
847 bytes
= read (fd
, &ifMsg
, sizeof ifMsg
);
850 Warn ("read from routing socket failed");
854 if (ifMsg
.ifm_version
!= RTM_VERSION
) {
856 Warn ("unexpected packet read from routing socket");
861 printf ("Routing message %#x received.\n", ifMsg
.ifm_type
);
863 if ((ifMsg
.ifm_type
== RTM_NEWADDR
|| ifMsg
.ifm_type
== RTM_IFINFO
) &&
864 ifMsg
.ifm_index
== ifIndex
) {
866 printf("Interface address/MTU has probably changed.\n");
871 static void DiscardIncomingPackets (int fd
)
873 struct sockaddr_in sin
;
875 socklen_t slen
= sizeof(sin
);
877 while (recvfrom(fd
, buffer
, sizeof(buffer
), 0, (struct sockaddr
*)&sin
, &slen
) != -1) {
886 struct mach_timebase_info info
;
888 (void) mach_timebase_info (&info
);
890 secdivisor
= ( (double)info
.denom
/ (double)info
.numer
) * 1000;
899 now
= mach_absolute_time();
900 epochtime
= (now
/ secdivisor
) / USEC_PER_SEC
;
901 return ( epochtime
);
905 /* set up neccessary info for doing NatPortMapP */
906 static void NatPortMapPInit()
909 struct ifaddrs
*ifap
, *ifa
;
911 forwardedinterfaceaddr
= (struct in_addr
*)
912 malloc(numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
913 bzero(forwardedinterfaceaddr
,
914 numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
915 /* interface address hasn't been set up, get interface address */
917 if (getifaddrs(&ifap
) == -1)
918 Quit ("getifaddrs failed.");
920 for ( ifa
= ifap
; ifa
; ifa
=ifa
->ifa_next
)
922 struct sockaddr_in
* a
;
923 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
927 a
= (struct sockaddr_in
*)ifa
->ifa_addr
;
928 for ( i
= 0; i
< numofinterfaces
; i
++ )
930 if (strcmp(ifa
->ifa_name
, forwardedinterfacename
[i
]))
934 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
936 /* copy the first IP address */
937 forwardedinterfaceaddr
[i
] = a
->sin_addr
;
946 /* SendPortMapResponse */
947 /* send generic reponses to NATPORTMAP requests */
948 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
)
953 reply
.version
= NATPMVERSION
;
954 reply
.opcode
= origopcode
+ SERVERREPLYOP
;
955 reply
.result
= htons(result
);
956 reply
.epoch
= htonl(getuptime());
957 bytes
= sendto( fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
958 if ( bytes
!= sizeof(reply
) )
959 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
962 /* SendPublicAddress */
963 /* return public address to requestor */
964 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
)
967 publicaddrreply reply
;
970 reply
.version
= NATPMVERSION
;
971 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
972 reply
.result
= SUCCESS
;
973 reply
.addr
= lastassignaliasAddr
;
974 reply
.epoch
= htonl(getuptime());
976 bytes
= sendto (fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
977 if ( bytes
!= sizeof(reply
) )
978 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
981 /* SendPublicPortResponse */
982 /* response for portmap request and portmap removal request */
983 /* publicport <= 0 means error */
984 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
, u_short publicport
, int result
)
988 publicportreply reply
;
990 bzero(&reply
, sizeof(publicportreply
));
991 reply
.version
= NATPMVERSION
;
992 reply
.opcode
= SERVERREPLYOP
+ req
->opcode
;
994 /* error in port mapping */
995 reply
.result
= htons(OUTOFRESOURCES
);
997 reply
.result
= SUCCESS
;
999 reply
.epoch
= htonl(getuptime());
1001 reply
.privateport
= req
->privateport
;
1003 /* adding or renewing a mapping */
1004 if ( req
->lifetime
) {
1005 reply
.publicport
= publicport
;
1006 reply
.lifetime
= req
->lifetime
;
1008 bytes
= sendto (fd
, (void*)&reply
, sizeof(publicportreply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
1009 if ( bytes
!= sizeof(publicportreply
) )
1010 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", req
->opcode
);
1013 /* SendPortMapMulti */
1014 /* send multicast to local network for new alias address */
1015 static void SendPortMapMulti()
1018 publicaddrreply reply
;
1020 struct sockaddr_in multiaddr
;
1024 #define LOCALGROUP "224.0.0.1"
1026 memset(&multiaddr
,0,sizeof(struct sockaddr_in
));
1027 multiaddr
.sin_family
=AF_INET
;
1028 multiaddr
.sin_addr
.s_addr
=inet_addr(LOCALGROUP
);
1029 multiaddr
.sin_port
=htons(NATPMP_ANNOUNCEMENT_PORT
);
1030 reply
.version
= NATPMVERSION
;
1031 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
1032 reply
.result
= SUCCESS
;
1033 reply
.addr
= lastassignaliasAddr
;
1036 /* send multicast to all forwarded interfaces */
1037 for ( i
= 0; i
< numofinterfaces
; i
++)
1039 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
1043 multisock
= socket( AF_INET
, SOCK_DGRAM
, 0);
1045 if ( multisock
== -1 )
1047 printf("cannot get socket for sending multicast\n");
1050 if (setsockopt(multisock
, IPPROTO_IP
, IP_MULTICAST_IF
, &forwardedinterfaceaddr
[i
], sizeof(struct in_addr
)) < 0)
1052 printf("setsockopt failed\n");
1056 bytes
= sendto (multisock
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)&multiaddr
, sizeof(multiaddr
));
1057 if ( bytes
!= sizeof(reply
) )
1058 printf( "PORTMAP::problem sending multicast alias address - opcode %d\n", reply
.opcode
);
1064 /* double the time value */
1065 static void Doubletime( struct timeval
*tvp
)
1068 timeradd(tvp
, tvp
, tvp
);
1072 /* stop running natd timer */
1073 static void Stoptimer()
1075 itval
.it_value
.tv_sec
= 0;
1076 itval
.it_value
.tv_usec
= 0;
1077 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1078 printf( "setitimer err: %d\n", errno
);
1082 /* timer routine to send new public IP address */
1083 static void Natdtimer()
1085 if ( !enable_natportmap
)
1090 if ( numoftries
< MAXRETRY
){
1091 Doubletime( &itval
.it_value
);
1092 itval
.it_interval
.tv_sec
= 0;
1093 itval
.it_interval
.tv_usec
= 0;
1094 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1095 printf( "setitimer err: %d\n", errno
);
1105 /* NotifyPublicAddress */
1106 /* Advertise new public address */
1107 static void NotifyPublicAddress()
1109 if ( numoftries
< MAXRETRY
)
1111 /* there is an old timer running, cancel it */
1114 /* send up new timer */
1117 itval
.it_value
.tv_sec
= 0;
1118 itval
.it_value
.tv_usec
= TIMER_RATE
;
1119 itval
.it_interval
.tv_sec
= 0;
1120 itval
.it_interval
.tv_usec
= 0;
1121 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1122 printf( "setitimer err: %d\n", errno
);
1127 /* find/add/remove port mapping from alias manager */
1128 void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
)
1130 u_char proto
= IPPROTO_TCP
;
1132 struct in_addr inany
= { INADDR_ANY
};
1134 if ( req
->opcode
== MAPUDPREQ
)
1135 proto
= IPPROTO_UDP
;
1136 if ( req
->lifetime
== 0)
1138 /* remove port mapping */
1139 if ( !FindAliasPortOut( clientaddr
->sin_addr
,
1144 ntohl(req
->lifetime
),
1146 /* FindAliasPortOut returns no error, port successfully removed, return no error response to client */
1147 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, 0, 0 );
1149 /* deleting port fails, return error */
1150 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, 0, -1 );
1154 /* look for port mapping - public port is ignored in this case */
1155 /* create port mapping - map provided public port to private port if public port is not 0 */
1156 aliasport
= FindAliasPortOut( clientaddr
->sin_addr
,
1157 inany
, /* lastassignaliasAddr */
1161 ntohl(req
->lifetime
),
1163 /* aliasport should be non zero if mapping is successfully, else -1 is returned, alias port shouldn't be zero???? */
1164 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, aliasport
, 0 );
1170 /* handle all packets sent to NATPORTMAP port */
1171 static void HandlePortMap( int fd
)
1173 #define MAXBUFFERSIZE 100
1175 struct sockaddr_in clientaddr
;
1176 socklen_t clientaddrlen
;
1177 unsigned char buffer
[MAXBUFFERSIZE
];
1179 unsigned short result
= SUCCESS
;
1180 struct stdportmaprequest
*req
;
1182 clientaddrlen
= sizeof( clientaddr
);
1183 bytes
= recvfrom( fd
, buffer
, sizeof(buffer
), 0, (struct sockaddr
*)&clientaddr
, &clientaddrlen
);
1186 printf( "Read NATPM port error\n");
1189 else if ( bytes
< sizeof(stdportmaprequest
) )
1191 /* drop any requests that are too short */
1195 req
= (struct stdportmaprequest
*)buffer
;
1201 printf("HandlePortMap from %s:%u length= %d: ", inet_ntoa(clientaddr
.sin_addr
), clientaddr
.sin_port
, bytes
);
1202 for ( i
= 0; i
<bytes
; i
++)
1204 printf("%02x", buffer
[i
]);
1210 /* drop any reply packets that we receive on the floor */
1211 if ( req
->opcode
>= SERVERREPLYOP
)
1216 /* check client version */
1217 if ( req
->version
> NATPMVERSION
)
1218 result
= NOTSUPPORTEDVERSION
;
1219 else if ( !enable_natportmap
)
1220 /* natd wasn't launched with portmapping enabled */
1221 result
= NOTAUTHORIZED
;
1225 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, result
);
1229 switch ( req
->opcode
)
1233 if ( bytes
== sizeof(stdportmaprequest
) )
1234 SendPublicAddress(fd
, &clientaddr
, clientaddrlen
);
1242 if ( bytes
== sizeof(publicportreq
) )
1243 DoPortMapping( fd
, &clientaddr
, clientaddrlen
, (publicportreq
*)req
);
1249 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, UNSUPPORTEDOPCODE
);
1254 #endif /* NATPORTMAP */
1256 static void PrintPacket (struct ip
* ip
)
1258 printf ("%s", FormatPacket (ip
));
1261 static void SyslogPacket (struct ip
* ip
, int priority
, const char *label
)
1263 syslog (priority
, "%s %s", label
, FormatPacket (ip
));
1266 static char* FormatPacket (struct ip
* ip
)
1268 static char buf
[256];
1269 struct tcphdr
* tcphdr
;
1270 struct udphdr
* udphdr
;
1271 struct icmp
* icmphdr
;
1275 strcpy (src
, inet_ntoa (ip
->ip_src
));
1276 strcpy (dst
, inet_ntoa (ip
->ip_dst
));
1280 tcphdr
= (struct tcphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1281 sprintf (buf
, "[TCP] %s:%d -> %s:%d",
1283 ntohs (tcphdr
->th_sport
),
1285 ntohs (tcphdr
->th_dport
));
1289 udphdr
= (struct udphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1290 sprintf (buf
, "[UDP] %s:%d -> %s:%d",
1292 ntohs (udphdr
->uh_sport
),
1294 ntohs (udphdr
->uh_dport
));
1298 icmphdr
= (struct icmp
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1299 sprintf (buf
, "[ICMP] %s -> %s %u(%u)",
1303 icmphdr
->icmp_code
);
1307 sprintf (buf
, "[%d] %s -> %s ", ip
->ip_p
, src
, dst
);
1315 SetAliasAddressFromIfName(const char *ifn
)
1319 char *buf
, *lim
, *next
;
1320 struct if_msghdr
*ifm
;
1321 struct ifa_msghdr
*ifam
;
1322 struct sockaddr_dl
*sdl
;
1323 struct sockaddr_in
*sin
;
1328 mib
[3] = AF_INET
; /* Only IP addresses please */
1329 mib
[4] = NET_RT_IFLIST
;
1330 mib
[5] = 0; /* ifIndex??? */
1332 * Get interface data.
1334 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1)
1335 err(1, "iflist-sysctl-estimate");
1336 if ((buf
= malloc(needed
)) == NULL
)
1337 errx(1, "malloc failed");
1338 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1)
1339 err(1, "iflist-sysctl-get");
1342 * Loop through interfaces until one with
1343 * given name is found. This is done to
1344 * find correct interface index for routing
1345 * message processing.
1349 while (next
< lim
) {
1350 ifm
= (struct if_msghdr
*)next
;
1351 next
+= ifm
->ifm_msglen
;
1352 if (ifm
->ifm_version
!= RTM_VERSION
) {
1354 warnx("routing message version %d "
1355 "not understood", ifm
->ifm_version
);
1358 if (ifm
->ifm_type
== RTM_IFINFO
) {
1359 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
1360 if (strlen(ifn
) == sdl
->sdl_nlen
&&
1361 strncmp(ifn
, sdl
->sdl_data
, sdl
->sdl_nlen
) == 0) {
1362 ifIndex
= ifm
->ifm_index
;
1363 ifMTU
= ifm
->ifm_data
.ifi_mtu
;
1365 PacketAliasClampMSS(ifMTU
- sizeof(struct tcphdr
) - sizeof(struct ip
));
1371 errx(1, "unknown interface name %s", ifn
);
1373 * Get interface address.
1375 if (aliasAddr
.s_addr
== INADDR_NONE
) {
1377 while (next
< lim
) {
1378 ifam
= (struct ifa_msghdr
*)next
;
1379 next
+= ifam
->ifam_msglen
;
1380 if (ifam
->ifam_version
!= RTM_VERSION
) {
1382 warnx("routing message version %d "
1383 "not understood", ifam
->ifam_version
);
1386 if (ifam
->ifam_type
!= RTM_NEWADDR
)
1388 if (ifam
->ifam_addrs
& RTA_IFA
) {
1390 char *cp
= (char *)(ifam
+ 1);
1392 #define ROUNDUP(a) \
1393 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
1394 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
1396 for (i
= 1; i
< RTA_IFA
; i
<<= 1)
1397 if (ifam
->ifam_addrs
& i
)
1398 ADVANCE(cp
, (struct sockaddr
*)cp
);
1399 if (((struct sockaddr
*)cp
)->sa_family
== AF_INET
) {
1400 sin
= (struct sockaddr_in
*)cp
;
1406 errx(1, "%s: cannot get interface address", ifn
);
1408 PacketAliasSetAddress(sin
->sin_addr
);
1410 if ( (enable_natportmap
) && (sin
->sin_addr
.s_addr
!= lastassignaliasAddr
.s_addr
) )
1412 lastassignaliasAddr
.s_addr
= sin
->sin_addr
.s_addr
;
1413 /* make sure the timer handler was set before setting timer */
1414 if ( !Natdtimerset
){
1416 signal(SIGALRM
, Natdtimer
);
1418 NotifyPublicAddress();
1421 syslog(LOG_INFO
, "Aliasing to %s, mtu %d bytes",
1422 inet_ntoa(sin
->sin_addr
), ifMTU
);
1428 void Quit (const char* msg
)
1434 void Warn (const char* msg
)
1437 syslog (LOG_ALERT
, "%s (%m)", msg
);
1442 static void RefreshAddr (int sig
)
1445 assignAliasAddr
= 1;
1448 static void InitiateShutdown (int sig
)
1451 * Start timer to allow kernel gracefully
1452 * shutdown existing connections when system
1455 siginterrupt(SIGALRM
, 1);
1456 signal (SIGALRM
, Shutdown
);
1460 static void Shutdown (int sig
)
1465 static void HandleInfo (int sig
)
1471 * Different options recognized by this program.
1511 * Option information structure (used by ParseOption).
1519 const char* parmDescription
;
1520 const char* description
;
1522 const char* shortName
;
1526 * Table of known options.
1529 static struct OptionInfo optionTable
[] = {
1531 { PacketAliasOption
,
1532 PKT_ALIAS_UNREGISTERED_ONLY
,
1535 "alias only unregistered addresses",
1536 "unregistered_only",
1539 { PacketAliasOption
,
1547 { PacketAliasOption
,
1548 PKT_ALIAS_PROXY_ONLY
,
1555 { PacketAliasOption
,
1559 "operate in reverse mode",
1563 { PacketAliasOption
,
1564 PKT_ALIAS_DENY_INCOMING
,
1567 "allow incoming connections",
1571 { PacketAliasOption
,
1572 PKT_ALIAS_USE_SOCKETS
,
1575 "use sockets to inhibit port conflict",
1579 { PacketAliasOption
,
1580 PKT_ALIAS_SAME_PORTS
,
1583 "try to keep original port numbers for connections",
1591 "verbose mode, dump packet information",
1599 "dynamic mode, automatically detect interface address changes",
1607 "enable TCP MSS clamping",
1614 "number|service_name",
1615 "set port for incoming packets",
1622 "number|service_name",
1623 "set port for outgoing packets",
1630 "number|service_name",
1631 "set port (defaults to natd/divert)",
1639 "address to use for aliasing",
1647 "address to use for incoming sessions",
1655 "take aliasing address from interface",
1662 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1664 "add transparent proxying / destination NAT",
1671 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range"
1672 " [remote_addr[:remote_port_range]]",
1673 "redirect a port (or ports) for incoming traffic",
1680 "proto local_addr [public_addr] [remote_addr]",
1681 "redirect packets of a given proto",
1688 "local_addr[,...] public_addr",
1689 "define mapping between local and public addresses",
1697 "read options from configuration file",
1705 "enable logging of denied incoming packets",
1713 "name of syslog facility to use for logging",
1721 "punch holes in the firewall for incoming FTP/IRC DCC connections",
1730 "enable NATPortMap protocol",
1731 "enable_natportmap",
1738 "take aliasing address to interface",
1739 "natportmap_interface",
1745 static void ParseOption (const char* option
, const char* parms
)
1748 struct OptionInfo
* info
;
1753 const char* strValue
;
1754 struct in_addr addrValue
;
1757 CODE
* fac_record
= NULL
;
1759 * Find option from table.
1761 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1762 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1764 if (!strcmp (info
->name
, option
))
1767 if (info
->shortName
)
1768 if (!strcmp (info
->shortName
, option
))
1774 warnx ("unknown option %s", option
);
1785 switch (info
->parm
) {
1790 if (!strcmp (parms
, "yes"))
1793 if (!strcmp (parms
, "no"))
1796 errx (1, "%s needs yes/no parameter", option
);
1801 errx (1, "%s needs service name or "
1802 "port number parameter",
1805 uNumValue
= StrToPort (parms
, "divert");
1810 numValue
= strtol (parms
, &end
, 10);
1815 errx (1, "%s needs numeric parameter", option
);
1821 errx (1, "%s needs parameter", option
);
1826 errx (1, "%s does not take parameters", option
);
1831 errx (1, "%s needs address/host parameter", option
);
1833 StrToAddr (parms
, &addrValue
);
1837 switch (info
->type
) {
1838 case PacketAliasOption
:
1840 aliasValue
= yesNoValue
? info
->packetAliasOpt
: 0;
1841 PacketAliasSetMode (aliasValue
, info
->packetAliasOpt
);
1845 verbose
= yesNoValue
;
1849 dynamicMode
= yesNoValue
;
1853 clampMSS
= yesNoValue
;
1861 outPort
= uNumValue
;
1865 inOutPort
= uNumValue
;
1869 memcpy (&aliasAddr
, &addrValue
, sizeof (struct in_addr
));
1873 PacketAliasSetTarget(addrValue
);
1877 SetupPortRedirect (strValue
);
1881 SetupProtoRedirect(strValue
);
1884 case RedirectAddress
:
1885 SetupAddressRedirect (strValue
);
1889 PacketAliasProxyRule (strValue
);
1896 ifName
= strdup (strValue
);
1900 ReadConfigFile (strValue
);
1909 fac_record
= facilitynames
;
1910 while (fac_record
->c_name
!= NULL
) {
1912 if (!strcmp (fac_record
->c_name
, strValue
)) {
1914 logFacility
= fac_record
->c_val
;
1922 if(fac_record
->c_name
== NULL
)
1923 errx(1, "Unknown log facility name: %s", strValue
);
1928 SetupPunchFW(strValue
);
1933 enable_natportmap
= yesNoValue
;
1937 case ToInterfaceName
:
1939 if (forwardedinterfacename
!= NULL
)
1941 if ( (forwardedinterfacename
= realloc( forwardedinterfacename
, (numofinterfaces
+1) * sizeof(*forwardedinterfacename
))) == NULL
){
1942 printf("realloc error, cannot allocate memory for fowarded interface name.\n");
1947 if ( (forwardedinterfacename
= malloc( sizeof(*forwardedinterfacename
) )) == NULL
){
1948 printf("malloc error, cannot allocate memory for fowarded interface name.\n");
1953 forwardedinterfacename
[numofinterfaces
] = strdup(strValue
);
1964 void ReadConfigFile (const char* fileName
)
1972 file
= fopen (fileName
, "r");
1974 err(1, "cannot open config file %s", fileName
);
1976 while ((buf
= fgetln(file
, &len
)) != NULL
) {
1977 if (buf
[len
- 1] == '\n')
1978 buf
[len
- 1] = '\0';
1980 errx(1, "config file format error: "
1981 "last line should end with newline");
1984 * Check for comments, strip off trailing spaces.
1986 if ((ptr
= strchr(buf
, '#')))
1988 for (ptr
= buf
; isspace(*ptr
); ++ptr
)
1992 for (p
= strchr(buf
, '\0'); isspace(*--p
);)
1997 * Extract option name.
2000 while (*ptr
&& !isspace (*ptr
))
2009 * Skip white space between name and parms.
2011 while (*ptr
&& isspace (*ptr
))
2014 ParseOption (option
, *ptr
? ptr
: NULL
);
2020 static void Usage ()
2024 struct OptionInfo
* info
;
2026 fprintf (stderr
, "Recognized options:\n\n");
2028 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
2029 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
2031 fprintf (stderr
, "-%-20s %s\n", info
->name
,
2032 info
->parmDescription
);
2034 if (info
->shortName
)
2035 fprintf (stderr
, "-%-20s %s\n", info
->shortName
,
2036 info
->parmDescription
);
2038 fprintf (stderr
, " %s\n\n", info
->description
);
2044 void SetupPortRedirect (const char* parms
)
2049 struct in_addr localAddr
;
2050 struct in_addr publicAddr
;
2051 struct in_addr remoteAddr
;
2052 port_range portRange
;
2053 u_short localPort
= 0;
2054 u_short publicPort
= 0;
2055 u_short remotePort
= 0;
2056 u_short numLocalPorts
= 0;
2057 u_short numPublicPorts
= 0;
2058 u_short numRemotePorts
= 0;
2063 struct alias_link
*link
= NULL
;
2065 strcpy (buf
, parms
);
2069 protoName
= strtok (buf
, " \t");
2071 errx (1, "redirect_port: missing protocol");
2073 proto
= StrToProto (protoName
);
2075 * Extract local address.
2077 ptr
= strtok (NULL
, " \t");
2079 errx (1, "redirect_port: missing local address");
2081 separator
= strchr(ptr
, ',');
2082 if (separator
) { /* LSNAT redirection syntax. */
2083 localAddr
.s_addr
= INADDR_NONE
;
2088 if ( StrToAddrAndPortRange (ptr
, &localAddr
, protoName
, &portRange
) != 0 )
2089 errx (1, "redirect_port: invalid local port range");
2091 localPort
= GETLOPORT(portRange
);
2092 numLocalPorts
= GETNUMPORTS(portRange
);
2097 * Extract public port and optionally address.
2099 ptr
= strtok (NULL
, " \t");
2101 errx (1, "redirect_port: missing public port");
2103 separator
= strchr (ptr
, ':');
2105 if (StrToAddrAndPortRange (ptr
, &publicAddr
, protoName
, &portRange
) != 0 )
2106 errx (1, "redirect_port: invalid public port range");
2109 publicAddr
.s_addr
= INADDR_ANY
;
2110 if (StrToPortRange (ptr
, protoName
, &portRange
) != 0)
2111 errx (1, "redirect_port: invalid public port range");
2114 publicPort
= GETLOPORT(portRange
);
2115 numPublicPorts
= GETNUMPORTS(portRange
);
2118 * Extract remote address and optionally port.
2120 ptr
= strtok (NULL
, " \t");
2122 separator
= strchr (ptr
, ':');
2124 if (StrToAddrAndPortRange (ptr
, &remoteAddr
, protoName
, &portRange
) != 0)
2125 errx (1, "redirect_port: invalid remote port range");
2127 SETLOPORT(portRange
, 0);
2128 SETNUMPORTS(portRange
, 1);
2129 StrToAddr (ptr
, &remoteAddr
);
2133 SETLOPORT(portRange
, 0);
2134 SETNUMPORTS(portRange
, 1);
2135 remoteAddr
.s_addr
= INADDR_ANY
;
2138 remotePort
= GETLOPORT(portRange
);
2139 numRemotePorts
= GETNUMPORTS(portRange
);
2142 * Make sure port ranges match up, then add the redirect ports.
2144 if (numLocalPorts
!= numPublicPorts
)
2145 errx (1, "redirect_port: port ranges must be equal in size");
2147 /* Remote port range is allowed to be '0' which means all ports. */
2148 if (numRemotePorts
!= numLocalPorts
&& (numRemotePorts
!= 1 || remotePort
!= 0))
2149 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
2151 for (i
= 0 ; i
< numPublicPorts
; ++i
) {
2152 /* If remotePort is all ports, set it to 0. */
2153 u_short remotePortCopy
= remotePort
+ i
;
2154 if (numRemotePorts
== 1 && remotePort
== 0)
2157 link
= PacketAliasRedirectPort (localAddr
,
2158 htons(localPort
+ i
),
2160 htons(remotePortCopy
),
2162 htons(publicPort
+ i
),
2167 * Setup LSNAT server pool.
2169 if (serverPool
!= NULL
&& link
!= NULL
) {
2170 ptr
= strtok(serverPool
, ",");
2171 while (ptr
!= NULL
) {
2172 if (StrToAddrAndPortRange(ptr
, &localAddr
, protoName
, &portRange
) != 0)
2173 errx(1, "redirect_port: invalid local port range");
2175 localPort
= GETLOPORT(portRange
);
2176 if (GETNUMPORTS(portRange
) != 1)
2177 errx(1, "redirect_port: local port must be single in this context");
2178 PacketAliasAddServer(link
, localAddr
, htons(localPort
));
2179 ptr
= strtok(NULL
, ",");
2185 SetupProtoRedirect(const char* parms
)
2189 struct in_addr localAddr
;
2190 struct in_addr publicAddr
;
2191 struct in_addr remoteAddr
;
2194 struct protoent
*protoent
;
2196 strcpy (buf
, parms
);
2200 protoName
= strtok(buf
, " \t");
2202 errx(1, "redirect_proto: missing protocol");
2204 protoent
= getprotobyname(protoName
);
2205 if (protoent
== NULL
)
2206 errx(1, "redirect_proto: unknown protocol %s", protoName
);
2208 proto
= protoent
->p_proto
;
2210 * Extract local address.
2212 ptr
= strtok(NULL
, " \t");
2214 errx(1, "redirect_proto: missing local address");
2216 StrToAddr(ptr
, &localAddr
);
2218 * Extract optional public address.
2220 ptr
= strtok(NULL
, " \t");
2222 StrToAddr(ptr
, &publicAddr
);
2224 publicAddr
.s_addr
= INADDR_ANY
;
2226 * Extract optional remote address.
2228 ptr
= strtok(NULL
, " \t");
2230 StrToAddr(ptr
, &remoteAddr
);
2232 remoteAddr
.s_addr
= INADDR_ANY
;
2234 * Create aliasing link.
2236 (void)PacketAliasRedirectProto(localAddr
, remoteAddr
, publicAddr
,
2240 void SetupAddressRedirect (const char* parms
)
2245 struct in_addr localAddr
;
2246 struct in_addr publicAddr
;
2248 struct alias_link
*link
;
2250 strcpy (buf
, parms
);
2252 * Extract local address.
2254 ptr
= strtok (buf
, " \t");
2256 errx (1, "redirect_address: missing local address");
2258 separator
= strchr(ptr
, ',');
2259 if (separator
) { /* LSNAT redirection syntax. */
2260 localAddr
.s_addr
= INADDR_NONE
;
2263 StrToAddr (ptr
, &localAddr
);
2267 * Extract public address.
2269 ptr
= strtok (NULL
, " \t");
2271 errx (1, "redirect_address: missing public address");
2273 StrToAddr (ptr
, &publicAddr
);
2274 link
= PacketAliasRedirectAddr(localAddr
, publicAddr
);
2277 * Setup LSNAT server pool.
2279 if (serverPool
!= NULL
&& link
!= NULL
) {
2280 ptr
= strtok(serverPool
, ",");
2281 while (ptr
!= NULL
) {
2282 StrToAddr(ptr
, &localAddr
);
2283 PacketAliasAddServer(link
, localAddr
, htons(~0));
2284 ptr
= strtok(NULL
, ",");
2289 void StrToAddr (const char* str
, struct in_addr
* addr
)
2293 if (inet_aton (str
, addr
))
2296 hp
= gethostbyname (str
);
2298 errx (1, "unknown host %s", str
);
2300 memcpy (addr
, hp
->h_addr
, sizeof (struct in_addr
));
2303 u_short
StrToPort (const char* str
, const char* proto
)
2309 port
= strtol (str
, &end
, 10);
2311 return htons (port
);
2313 sp
= getservbyname (str
, proto
);
2315 errx (1, "unknown service %s/%s", str
, proto
);
2320 int StrToPortRange (const char* str
, const char* proto
, port_range
*portRange
)
2328 /* First see if this is a service, return corresponding port if so. */
2329 sp
= getservbyname (str
,proto
);
2331 SETLOPORT(*portRange
, ntohs(sp
->s_port
));
2332 SETNUMPORTS(*portRange
, 1);
2336 /* Not a service, see if it's a single port or port range. */
2337 sep
= strchr (str
, '-');
2339 SETLOPORT(*portRange
, strtol(str
, &end
, 10));
2342 SETNUMPORTS(*portRange
, 1);
2346 /* Error in port range field. */
2347 errx (1, "unknown service %s/%s", str
, proto
);
2350 /* Port range, get the values and sanity check. */
2351 sscanf (str
, "%hu-%hu", &loPort
, &hiPort
);
2352 SETLOPORT(*portRange
, loPort
);
2353 SETNUMPORTS(*portRange
, 0); /* Error by default */
2354 if (loPort
<= hiPort
)
2355 SETNUMPORTS(*portRange
, hiPort
- loPort
+ 1);
2357 if (GETNUMPORTS(*portRange
) == 0)
2358 errx (1, "invalid port range %s", str
);
2364 int StrToProto (const char* str
)
2366 if (!strcmp (str
, "tcp"))
2369 if (!strcmp (str
, "udp"))
2372 errx (1, "unknown protocol %s. Expected tcp or udp", str
);
2375 int StrToAddrAndPortRange (const char* str
, struct in_addr
* addr
, char* proto
, port_range
*portRange
)
2379 ptr
= strchr (str
, ':');
2381 errx (1, "%s is missing port number", str
);
2386 StrToAddr (str
, addr
);
2387 return StrToPortRange (ptr
, proto
, portRange
);
2391 SetupPunchFW(const char *strValue
)
2393 unsigned int base
, num
;
2395 if (sscanf(strValue
, "%u:%u", &base
, &num
) != 2)
2396 errx(1, "punch_fw: basenumber:count parameter required");
2398 PacketAliasSetFWBase(base
, num
);
2399 (void)PacketAliasSetMode(PKT_ALIAS_PUNCH_FW
, PKT_ALIAS_PUNCH_FW
);