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>
68 #include <mach/mach_time.h>
69 #include <mach/clock_types.h>
74 * Default values for input and output
75 * divert socket ports.
78 #define DEFAULT_SERVICE "natd"
81 * Definition of a port range, and macros to deal with values.
82 * FORMAT: HI 16-bits == first port in range, 0 == all ports.
83 * LO 16-bits == number of ports in range
84 * NOTES: - Port values are not stored in network byte order.
87 typedef u_long port_range
;
89 #define GETLOPORT(x) ((x) >> 0x10)
90 #define GETNUMPORTS(x) ((x) & 0x0000ffff)
91 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
93 /* Set y to be the low-port value in port_range variable x. */
94 #define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
96 /* Set y to be the number of ports in port_range variable x. */
97 #define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
100 * Function prototypes.
103 static void DoAliasing (int fd
, int direction
);
104 static void DaemonMode (void);
105 static void HandleRoutingInfo (int fd
);
106 static void Usage (void);
107 static char* FormatPacket (struct ip
*);
108 static void PrintPacket (struct ip
*);
109 static void SyslogPacket (struct ip
*, int priority
, const char *label
);
110 static void SetAliasAddressFromIfName (const char *ifName
);
111 static void InitiateShutdown (int);
112 static void Shutdown (int);
113 static void RefreshAddr (int);
114 static void HandleInfo (int);
115 static void ParseOption (const char* option
, const char* parms
);
116 static void ReadConfigFile (const char* fileName
);
117 static void SetupPortRedirect (const char* parms
);
118 static void SetupProtoRedirect(const char* parms
);
119 static void SetupAddressRedirect (const char* parms
);
120 static void StrToAddr (const char* str
, struct in_addr
* addr
);
121 static u_short
StrToPort (const char* str
, const char* proto
);
122 static int StrToPortRange (const char* str
, const char* proto
, port_range
*portRange
);
123 static int StrToProto (const char* str
);
124 static int StrToAddrAndPortRange (const char* str
, struct in_addr
* addr
, char* proto
, port_range
*portRange
);
125 static void ParseArgs (int argc
, char** argv
);
126 static void FlushPacketBuffer (int fd
);
127 static void SetupPunchFW(const char *strValue
);
134 static int background
;
136 static int assignAliasAddr
;
139 static u_short inPort
;
140 static u_short outPort
;
141 static u_short inOutPort
;
142 static struct in_addr aliasAddr
;
143 static int dynamicMode
;
146 static int aliasOverhead
;
148 static char packetBuf
[IP_MAXPACKET
];
149 static int packetLen
;
150 static struct sockaddr_in packetAddr
;
151 static int packetSock
;
152 static int packetDirection
;
153 static int dropIgnoredIncoming
;
154 static int logDropped
;
155 static int logFacility
;
161 #define NATPMPORT 5351
163 #define NATPMVERSION 0
164 #define PUBLICADDRREQ 0
167 #define MAPUDPTCPREQ 3
168 #define SERVERREPLYOP 128
169 #define PUBLICADDRRLY SERVERREPLYOP+PUBLICADDRREQ
172 #define NOTSUPPORTEDVERSION 1
173 #define NOTAUTHORIZED 2
174 #define NETWORKFAILURE 3
175 #define OUTOFRESOURCES 4
176 #define UNSUPPORTEDOPCODE 5
178 #define TIMER_RATE 250000
182 typedef struct stdportmaprequest
{
184 unsigned char opcode
;
185 unsigned short result
;
189 typedef struct publicaddrreply
{
191 unsigned char opcode
;
192 unsigned short result
;
197 typedef struct publicportreq
{
199 unsigned char opcode
;
200 unsigned short result
;
201 unsigned short privateport
;
202 unsigned short publicport
;
203 int lifetime
; /* in second */
206 typedef struct publicportreply
{
208 unsigned char opcode
;
209 unsigned short result
;
211 unsigned short privateport
;
212 unsigned short publicport
;
213 int lifetime
; /* in second */
216 typedef struct stderrreply
{
218 unsigned char opcode
;
219 unsigned short result
;
224 static int enable_natportmap
= 0;
225 static struct in_addr lastassignaliasAddr
;
226 static int portmapSock
= -1;
227 static struct in_addr
*forwardedinterfaceaddr
;
228 static char **forwardedinterfacename
;
229 static int numofinterfaces
= 0; /* has to be at least one */
230 static u_short natPMPport
;
231 static int numoftries
=MAXRETRY
;
232 static struct itimerval itval
;
233 static int Natdtimerset
= 0;
234 static double secdivisor
;
237 static void HandlePortMap( int fd
);
238 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
);
239 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
);
240 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*reply
, u_short publicport
, int result
);
241 static void Doubletime( struct timeval
*tvp
);
242 static void Stoptimer();
243 static void Natdtimer();
244 static void SendPortMapMulti( );
245 static void NotifyPublicAddress();
246 static void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
);
247 static void NatPortMapPInit();
248 static u_short
get_natportmap_port(void);
250 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
);
254 int main (int argc
, char** argv
)
260 struct sockaddr_in addr
;
265 * Initialize packet aliasing software.
266 * Done already here to be able to alter option bits
267 * during command line and configuration file processing.
282 aliasAddr
.s_addr
= INADDR_NONE
;
284 lastassignaliasAddr
.s_addr
= INADDR_NONE
;
289 logFacility
= LOG_DAEMON
;
291 * Mark packet buffer empty.
294 packetDirection
= DONT_KNOW
;
296 ParseArgs (argc
, argv
);
298 * Open syslog channel.
300 openlog ("natd", LOG_CONS
| LOG_PID
| (verbose
? LOG_PERROR
: 0),
303 * Check that valid aliasing address has been given.
305 if (aliasAddr
.s_addr
== INADDR_NONE
&& ifName
== NULL
)
306 errx (1, "aliasing address not given");
309 * Check that valid port number is known.
311 if (inPort
!= 0 || outPort
!= 0)
312 if (inPort
== 0 || outPort
== 0)
313 errx (1, "both input and output ports are required");
315 if (inPort
== 0 && outPort
== 0 && inOutPort
== 0)
316 ParseOption ("port", DEFAULT_SERVICE
);
319 * Check if ignored packets should be dropped.
321 dropIgnoredIncoming
= PacketAliasSetMode (0, 0);
322 dropIgnoredIncoming
&= PKT_ALIAS_DENY_INCOMING
;
324 * Create divert sockets. Use only one socket if -p was specified
325 * on command line. Otherwise, create separate sockets for
326 * outgoing and incoming connnections.
330 divertInOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
331 if (divertInOut
== -1)
332 Quit ("Unable to create divert socket.");
340 addr
.sin_family
= AF_INET
;
341 addr
.sin_addr
.s_addr
= INADDR_ANY
;
342 addr
.sin_port
= inOutPort
;
344 if (bind (divertInOut
,
345 (struct sockaddr
*) &addr
,
347 Quit ("Unable to bind divert socket.");
351 divertIn
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
353 Quit ("Unable to create incoming divert socket.");
355 divertOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
357 Quit ("Unable to create outgoing divert socket.");
362 * Bind divert sockets.
365 addr
.sin_family
= AF_INET
;
366 addr
.sin_addr
.s_addr
= INADDR_ANY
;
367 addr
.sin_port
= inPort
;
370 (struct sockaddr
*) &addr
,
372 Quit ("Unable to bind incoming divert socket.");
374 addr
.sin_family
= AF_INET
;
375 addr
.sin_addr
.s_addr
= INADDR_ANY
;
376 addr
.sin_port
= outPort
;
379 (struct sockaddr
*) &addr
,
381 Quit ("Unable to bind outgoing divert socket.");
384 * Create routing socket if interface name specified and in dynamic mode.
390 routeSock
= socket (PF_ROUTE
, SOCK_RAW
, 0);
392 Quit ("Unable to create routing info socket.");
397 SetAliasAddressFromIfName (ifName
);
401 * Create socket for sending ICMP messages.
403 icmpSock
= socket (AF_INET
, SOCK_RAW
, IPPROTO_ICMP
);
405 Quit ("Unable to create ICMP socket.");
408 * And disable reads for the socket, otherwise it slowly fills
409 * up with received icmps which we do not use.
411 shutdown(icmpSock
, SHUT_RD
);
415 if ( enable_natportmap
)
417 /* create socket to listen for port mapping */
418 portmapSock
= socket( AF_INET
, SOCK_DGRAM
, 0);
419 if ( portmapSock
!= -1 )
421 natPMPport
= htons(get_natportmap_port());
422 addr
.sin_family
= AF_INET
;
423 addr
.sin_addr
.s_addr
= INADDR_ANY
;
424 addr
.sin_port
= htons(NATPMPORT
);
426 if (bind ( portmapSock
,
427 (struct sockaddr
*) &addr
,
429 printf("Binding to NATPM port failed!\n");
431 /* NATPORTMAPP initial set up */
434 if ( !Natdtimerset
){
436 signal(SIGALRM
, Natdtimer
);
441 * Become a daemon unless verbose mode was requested.
446 * Catch signals to manage shutdown and
447 * refresh of interface address.
449 siginterrupt(SIGTERM
, 1);
450 siginterrupt(SIGHUP
, 1);
451 signal (SIGTERM
, InitiateShutdown
);
452 signal (SIGHUP
, RefreshAddr
);
453 signal (SIGINFO
, HandleInfo
);
455 * Set alias address if it has been given.
457 if (aliasAddr
.s_addr
!= INADDR_NONE
)
459 PacketAliasSetAddress (aliasAddr
);
461 if ( (enable_natportmap
) && (aliasAddr
.s_addr
!= lastassignaliasAddr
.s_addr
) ){
462 lastassignaliasAddr
.s_addr
= aliasAddr
.s_addr
;
463 NotifyPublicAddress();
468 * We need largest descriptor number for select.
473 if (divertIn
> fdMax
)
476 if (divertOut
> fdMax
)
479 if (divertInOut
> fdMax
)
482 if (routeSock
> fdMax
)
486 if ( portmapSock
> fdMax
)
493 if (divertInOut
!= -1 && !ifName
&& packetSock
== -1) {
495 * When using only one socket, just call
496 * DoAliasing repeatedly to process packets.
498 DoAliasing (divertInOut
, DONT_KNOW
);
502 * Build read mask from socket descriptors to select.
505 FD_ZERO (&writeMask
);
508 * If there is unsent packet in buffer, use select
509 * to check when socket comes writable again.
511 if (packetSock
!= -1) {
513 FD_SET (packetSock
, &writeMask
);
517 * No unsent packet exists - safe to check if
518 * new ones are available.
521 FD_SET (divertIn
, &readMask
);
524 FD_SET (divertOut
, &readMask
);
526 if (divertInOut
!= -1)
527 FD_SET (divertInOut
, &readMask
);
530 * Routing info is processed always.
533 FD_SET (routeSock
, &readMask
);
535 if ( portmapSock
!= -1 )
536 FD_SET (portmapSock
, &readMask
);
538 if (select (fdMax
+ 1,
544 if (errno
== EINTR
) {
551 Quit ("Select failed.");
554 if (packetSock
!= -1)
555 if (FD_ISSET (packetSock
, &writeMask
))
556 FlushPacketBuffer (packetSock
);
559 if (FD_ISSET (divertIn
, &readMask
))
560 DoAliasing (divertIn
, INPUT
);
563 if (FD_ISSET (divertOut
, &readMask
))
564 DoAliasing (divertOut
, OUTPUT
);
566 if (divertInOut
!= -1)
567 if (FD_ISSET (divertInOut
, &readMask
))
568 DoAliasing (divertInOut
, DONT_KNOW
);
571 if (FD_ISSET (routeSock
, &readMask
))
572 HandleRoutingInfo (routeSock
);
574 if ( portmapSock
!= -1)
575 if (FD_ISSET (portmapSock
, &readMask
))
576 HandlePortMap( portmapSock
);
586 static void DaemonMode ()
593 pidFile
= fopen (PIDFILE
, "w");
596 fprintf (pidFile
, "%d\n", getpid ());
601 static void ParseArgs (int argc
, char** argv
)
606 int len
; /* bounds checking */
608 for (arg
= 1; arg
< argc
; arg
++) {
613 warnx ("invalid option %s", opt
);
620 while (arg
< argc
- 1) {
622 if (argv
[arg
+ 1][0] == '-')
626 strncat (parmBuf
, " ", sizeof(parmBuf
) - (len
+ 1));
627 len
+= strlen(parmBuf
+ len
);
631 strncat (parmBuf
, argv
[arg
], sizeof(parmBuf
) - (len
+ 1));
632 len
+= strlen(parmBuf
+ len
);
636 ParseOption (opt
+ 1, (len
? parmBuf
: NULL
));
641 static void DoAliasing (int fd
, int direction
)
649 if (assignAliasAddr
) {
651 SetAliasAddressFromIfName (ifName
);
655 * Get packet from socket.
657 addrSize
= sizeof packetAddr
;
658 origBytes
= recvfrom (fd
,
662 (struct sockaddr
*) &packetAddr
,
665 if (origBytes
== -1) {
668 Warn ("read from divert socket failed");
673 * This is a IP packet.
675 ip
= (struct ip
*) packetBuf
;
676 if (direction
== DONT_KNOW
) {
677 if (packetAddr
.sin_addr
.s_addr
== INADDR_ANY
)
685 * Print packet direction and protocol type.
687 printf (direction
== OUTPUT
? "Out " : "In ");
703 printf ("[%d] ", ip
->ip_p
);
712 if (direction
== OUTPUT
) {
714 * Outgoing packets. Do aliasing.
716 PacketAliasOut (packetBuf
, IP_MAXPACKET
);
723 status
= PacketAliasIn (packetBuf
, IP_MAXPACKET
);
724 if (status
== PKT_ALIAS_IGNORED
&&
725 dropIgnoredIncoming
) {
728 printf (" dropped.\n");
731 SyslogPacket (ip
, LOG_WARNING
, "denied");
737 * Length might have changed during aliasing.
739 bytes
= ntohs (ip
->ip_len
);
741 * Update alias overhead size for outgoing packets.
743 if (direction
== OUTPUT
&&
744 bytes
- origBytes
> aliasOverhead
)
745 aliasOverhead
= bytes
- origBytes
;
750 * Print addresses after aliasing.
752 printf (" aliased to\n");
760 packetDirection
= direction
;
762 FlushPacketBuffer (fd
);
765 static void FlushPacketBuffer (int fd
)
770 * Put packet back for processing.
776 (struct sockaddr
*) &packetAddr
,
779 if (wrote
!= packetLen
) {
781 * If buffer space is not available,
782 * just return. Main loop will take care of
783 * retrying send when space becomes available.
785 if (errno
== ENOBUFS
)
788 if (errno
== EMSGSIZE
) {
790 if (packetDirection
== OUTPUT
&&
792 SendNeedFragIcmp (icmpSock
,
793 (struct ip
*) packetBuf
,
794 ifMTU
- aliasOverhead
);
798 sprintf (msgBuf
, "failed to write packet back");
806 static void HandleRoutingInfo (int fd
)
809 struct if_msghdr ifMsg
;
811 * Get packet from socket.
813 bytes
= read (fd
, &ifMsg
, sizeof ifMsg
);
816 Warn ("read from routing socket failed");
820 if (ifMsg
.ifm_version
!= RTM_VERSION
) {
822 Warn ("unexpected packet read from routing socket");
827 printf ("Routing message %#x received.\n", ifMsg
.ifm_type
);
829 if ((ifMsg
.ifm_type
== RTM_NEWADDR
|| ifMsg
.ifm_type
== RTM_IFINFO
) &&
830 ifMsg
.ifm_index
== ifIndex
) {
832 printf("Interface address/MTU has probably changed.\n");
841 struct mach_timebase_info info
;
843 (void) mach_timebase_info (&info
);
845 secdivisor
= ( (double)info
.denom
/ (double)info
.numer
) * 1000;
849 unsigned int getuptime()
852 unsigned long epochtime
;
854 now
= mach_absolute_time();
855 epochtime
= (now
/ secdivisor
) /USEC_PER_SEC
;
860 /* return NATPORTMAP port defined in /etc/servcies if there's one, else use NATPMPORT */
861 static u_short
get_natportmap_port(void)
865 ent
= getservbyname( "natportmap", "udp" );
867 return( ent
->s_port
);
872 /* set up neccessary info for doing NatPortMapP */
873 static void NatPortMapPInit()
876 struct ifaddrs
*ifap
, *ifa
;
878 forwardedinterfaceaddr
= (struct in_addr
*)
879 malloc(numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
880 bzero(forwardedinterfaceaddr
,
881 numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
882 /* interface address hasn't been set up, get interface address */
884 for ( ifa
= ifap
; ifa
; ifa
=ifa
->ifa_next
)
886 struct sockaddr_in
* a
;
887 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
891 a
= (struct sockaddr_in
*)ifa
->ifa_addr
;
892 for ( i
= 0; i
< numofinterfaces
; i
++ )
894 if (strcmp(ifa
->ifa_name
, forwardedinterfacename
[i
]))
898 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
900 /* copy the first IP address */
901 forwardedinterfaceaddr
[i
] = a
->sin_addr
;
910 /* SendPortMapResponse */
911 /* send generic reponses to NATPORTMAP requests */
912 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
)
917 reply
.version
= NATPMVERSION
;
918 reply
.opcode
= origopcode
+ SERVERREPLYOP
;
919 reply
.result
= result
;
920 reply
.epoch
= getuptime();
921 bytes
= sendto( fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
922 if ( bytes
!= sizeof(reply
) )
923 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
926 /* SendPublicAddress */
927 /* return public address to requestor */
928 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
)
931 publicaddrreply reply
;
934 reply
.version
= NATPMVERSION
;
935 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
936 reply
.result
= SUCCESS
;
937 reply
.addr
= lastassignaliasAddr
;
938 reply
.epoch
= getuptime();
940 bytes
= sendto (fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
941 if ( bytes
!= sizeof(reply
) )
942 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
945 /* SendPublicPortResponse */
946 /* response for portmap request and portmap removal request */
947 /* publicport <= 0 means error */
948 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
, u_short publicport
, int result
)
952 publicportreply reply
;
954 bzero(&reply
, sizeof(publicportreply
));
955 reply
.version
= NATPMVERSION
;
956 reply
.opcode
= SERVERREPLYOP
+ req
->opcode
;
958 /* error in port mapping */
959 reply
.result
= OUTOFRESOURCES
;
961 reply
.result
= SUCCESS
;
963 reply
.epoch
= getuptime();
965 reply
.privateport
= req
->privateport
;
967 /* adding or renewing a mapping */
968 if ( req
->lifetime
) {
969 reply
.publicport
= publicport
;
970 reply
.lifetime
= req
->lifetime
;
972 bytes
= sendto (fd
, (void*)&reply
, sizeof(publicportreply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
973 if ( bytes
!= sizeof(publicportreply
) )
974 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", req
->opcode
);
977 /* SendPortMapMulti */
978 /* send multicast to local network for new alias address */
979 static void SendPortMapMulti()
982 publicaddrreply reply
;
984 struct sockaddr_in multiaddr
;
988 #define LOCALGROUP "224.0.0.1"
990 memset(&multiaddr
,0,sizeof(struct sockaddr_in
));
991 multiaddr
.sin_family
=AF_INET
;
992 multiaddr
.sin_addr
.s_addr
=inet_addr(LOCALGROUP
);
993 multiaddr
.sin_port
=htons(NATPMPORT
);
994 reply
.version
= NATPMVERSION
;
995 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
996 reply
.result
= SUCCESS
;
997 reply
.addr
= lastassignaliasAddr
;
1000 /* send multicast to all forwarded interfaces */
1001 for ( i
= 0; i
< numofinterfaces
; i
++)
1003 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
1007 multisock
= socket( AF_INET
, SOCK_DGRAM
, 0);
1009 if ( multisock
== -1 )
1011 printf("cannot get socket for sending multicast\n");
1014 if (setsockopt(multisock
, IPPROTO_IP
, IP_MULTICAST_IF
, &forwardedinterfaceaddr
[i
], sizeof(struct in_addr
)) < 0)
1016 printf("setsockopt failed\n");
1020 bytes
= sendto (multisock
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)&multiaddr
, sizeof(multiaddr
));
1021 if ( bytes
!= sizeof(reply
) )
1022 printf( "PORTMAP::problem sending multicast alias address - opcode %d\n", reply
.opcode
);
1028 /* double the time value */
1029 static void Doubletime( struct timeval
*tvp
)
1032 timeradd(tvp
, tvp
, tvp
);
1036 /* stop running natd timer */
1037 static void Stoptimer()
1039 itval
.it_value
.tv_sec
= 0;
1040 itval
.it_value
.tv_usec
= 0;
1041 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1042 printf( "setitimer err: %d\n", errno
);
1046 /* timer routine to send new public IP address */
1047 static void Natdtimer()
1049 if ( !enable_natportmap
)
1054 if ( numoftries
< MAXRETRY
){
1055 Doubletime( &itval
.it_value
);
1056 itval
.it_interval
.tv_sec
= 0;
1057 itval
.it_interval
.tv_usec
= 0;
1058 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1059 printf( "setitimer err: %d\n", errno
);
1069 /* NotifyPublicAddress */
1070 /* Advertise new public address */
1071 static void NotifyPublicAddress()
1073 if ( numoftries
< MAXRETRY
)
1075 /* there is an old timer running, cancel it */
1078 /* send up new timer */
1081 itval
.it_value
.tv_sec
= 0;
1082 itval
.it_value
.tv_usec
= TIMER_RATE
;
1083 itval
.it_interval
.tv_sec
= 0;
1084 itval
.it_interval
.tv_usec
= 0;
1085 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1086 printf( "setitimer err: %d\n", errno
);
1091 /* find/add/remove port mapping from alias manager */
1092 void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
)
1094 u_char proto
= IPPROTO_TCP
;
1096 struct in_addr inany
= { INADDR_ANY
};
1098 if ( req
->opcode
== MAPUDPREQ
)
1099 proto
= IPPROTO_UDP
;
1100 if ( req
->lifetime
== 0)
1102 /* remove port mapping */
1103 if ( !FindAliasPortOut( clientaddr
->sin_addr
, inany
, req
->privateport
, req
->publicport
, proto
, req
->lifetime
, 0))
1104 /* FindAliasPortOut returns no error, port successfully removed, return no error response to client */
1105 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, 0, 0 );
1107 /* deleting port fails, return error */
1108 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, 0, -1 );
1112 /* look for port mapping - public port is ignored in this case */
1113 /* create port mapping - map provided public port to private port if public port is not 0 */
1114 aliasport
= FindAliasPortOut( clientaddr
->sin_addr
,
1115 inany
, /* lastassignaliasAddr */
1121 /* aliasport should be non zero if mapping is successfully, else -1 is returned, alias port shouldn't be zero???? */
1122 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, aliasport
, 0 );
1128 /* handle all packets sent to NATPORTMAP port */
1129 static void HandlePortMap( int fd
)
1131 #define MAXBUFFERSIZE 100
1133 struct sockaddr_in clientaddr
;
1134 socklen_t clientaddrlen
;
1135 unsigned char buffer
[MAXBUFFERSIZE
];
1137 unsigned short result
= SUCCESS
;
1138 struct stdportmaprequest
*req
;
1140 clientaddrlen
= sizeof( clientaddr
);
1141 bytes
= recvfrom( fd
, buffer
, sizeof(buffer
), 0, (struct sockaddr
*)&clientaddr
, &clientaddrlen
);
1144 printf( "Read NATPM port error\n");
1147 req
= (struct stdportmaprequest
*)buffer
;
1153 printf("HandlePortMap from %s:%u length= %d: ", inet_ntoa(clientaddr
.sin_addr
), clientaddr
.sin_port
, bytes
);
1154 for ( i
= 0; i
<bytes
; i
++)
1156 printf("%02x", buffer
[i
]);
1161 /* check client version */
1162 if ( req
->version
> NATPMVERSION
)
1163 result
= NOTSUPPORTEDVERSION
;
1164 else if ( !enable_natportmap
)
1165 /* natd wasn't launched with portmapping enabled */
1166 result
= NOTAUTHORIZED
;
1170 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, result
);
1174 switch ( req
->opcode
)
1178 SendPublicAddress(fd
, &clientaddr
, clientaddrlen
);
1186 DoPortMapping( fd
, &clientaddr
, clientaddrlen
, (publicportreq
*)req
);
1192 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, UNSUPPORTEDOPCODE
);
1200 static void PrintPacket (struct ip
* ip
)
1202 printf ("%s", FormatPacket (ip
));
1205 static void SyslogPacket (struct ip
* ip
, int priority
, const char *label
)
1207 syslog (priority
, "%s %s", label
, FormatPacket (ip
));
1210 static char* FormatPacket (struct ip
* ip
)
1212 static char buf
[256];
1213 struct tcphdr
* tcphdr
;
1214 struct udphdr
* udphdr
;
1215 struct icmp
* icmphdr
;
1219 strcpy (src
, inet_ntoa (ip
->ip_src
));
1220 strcpy (dst
, inet_ntoa (ip
->ip_dst
));
1224 tcphdr
= (struct tcphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1225 sprintf (buf
, "[TCP] %s:%d -> %s:%d",
1227 ntohs (tcphdr
->th_sport
),
1229 ntohs (tcphdr
->th_dport
));
1233 udphdr
= (struct udphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1234 sprintf (buf
, "[UDP] %s:%d -> %s:%d",
1236 ntohs (udphdr
->uh_sport
),
1238 ntohs (udphdr
->uh_dport
));
1242 icmphdr
= (struct icmp
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1243 sprintf (buf
, "[ICMP] %s -> %s %u(%u)",
1247 icmphdr
->icmp_code
);
1251 sprintf (buf
, "[%d] %s -> %s ", ip
->ip_p
, src
, dst
);
1259 SetAliasAddressFromIfName(const char *ifn
)
1263 char *buf
, *lim
, *next
;
1264 struct if_msghdr
*ifm
;
1265 struct ifa_msghdr
*ifam
;
1266 struct sockaddr_dl
*sdl
;
1267 struct sockaddr_in
*sin
;
1272 mib
[3] = AF_INET
; /* Only IP addresses please */
1273 mib
[4] = NET_RT_IFLIST
;
1274 mib
[5] = 0; /* ifIndex??? */
1276 * Get interface data.
1278 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1)
1279 err(1, "iflist-sysctl-estimate");
1280 if ((buf
= malloc(needed
)) == NULL
)
1281 errx(1, "malloc failed");
1282 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1)
1283 err(1, "iflist-sysctl-get");
1286 * Loop through interfaces until one with
1287 * given name is found. This is done to
1288 * find correct interface index for routing
1289 * message processing.
1293 while (next
< lim
) {
1294 ifm
= (struct if_msghdr
*)next
;
1295 next
+= ifm
->ifm_msglen
;
1296 if (ifm
->ifm_version
!= RTM_VERSION
) {
1298 warnx("routing message version %d "
1299 "not understood", ifm
->ifm_version
);
1302 if (ifm
->ifm_type
== RTM_IFINFO
) {
1303 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
1304 if (strlen(ifn
) == sdl
->sdl_nlen
&&
1305 strncmp(ifn
, sdl
->sdl_data
, sdl
->sdl_nlen
) == 0) {
1306 ifIndex
= ifm
->ifm_index
;
1307 ifMTU
= ifm
->ifm_data
.ifi_mtu
;
1309 PacketAliasClampMSS(ifMTU
- sizeof(struct tcphdr
) - sizeof(struct ip
));
1315 errx(1, "unknown interface name %s", ifn
);
1317 * Get interface address.
1319 if (aliasAddr
.s_addr
== INADDR_NONE
) {
1321 while (next
< lim
) {
1322 ifam
= (struct ifa_msghdr
*)next
;
1323 next
+= ifam
->ifam_msglen
;
1324 if (ifam
->ifam_version
!= RTM_VERSION
) {
1326 warnx("routing message version %d "
1327 "not understood", ifam
->ifam_version
);
1330 if (ifam
->ifam_type
!= RTM_NEWADDR
)
1332 if (ifam
->ifam_addrs
& RTA_IFA
) {
1334 char *cp
= (char *)(ifam
+ 1);
1336 #define ROUNDUP(a) \
1337 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1338 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
1340 for (i
= 1; i
< RTA_IFA
; i
<<= 1)
1341 if (ifam
->ifam_addrs
& i
)
1342 ADVANCE(cp
, (struct sockaddr
*)cp
);
1343 if (((struct sockaddr
*)cp
)->sa_family
== AF_INET
) {
1344 sin
= (struct sockaddr_in
*)cp
;
1350 errx(1, "%s: cannot get interface address", ifn
);
1352 PacketAliasSetAddress(sin
->sin_addr
);
1354 if ( (enable_natportmap
) && (sin
->sin_addr
.s_addr
!= lastassignaliasAddr
.s_addr
) )
1356 lastassignaliasAddr
.s_addr
= sin
->sin_addr
.s_addr
;
1357 /* make sure the timer handler was set before setting timer */
1358 if ( !Natdtimerset
){
1360 signal(SIGALRM
, Natdtimer
);
1362 NotifyPublicAddress();
1365 syslog(LOG_INFO
, "Aliasing to %s, mtu %d bytes",
1366 inet_ntoa(sin
->sin_addr
), ifMTU
);
1372 void Quit (const char* msg
)
1378 void Warn (const char* msg
)
1381 syslog (LOG_ALERT
, "%s (%m)", msg
);
1386 static void RefreshAddr (int sig
)
1389 assignAliasAddr
= 1;
1392 static void InitiateShutdown (int sig
)
1395 * Start timer to allow kernel gracefully
1396 * shutdown existing connections when system
1399 siginterrupt(SIGALRM
, 1);
1400 signal (SIGALRM
, Shutdown
);
1404 static void Shutdown (int sig
)
1409 static void HandleInfo (int sig
)
1415 * Different options recognized by this program.
1455 * Option information structure (used by ParseOption).
1463 const char* parmDescription
;
1464 const char* description
;
1466 const char* shortName
;
1470 * Table of known options.
1473 static struct OptionInfo optionTable
[] = {
1475 { PacketAliasOption
,
1476 PKT_ALIAS_UNREGISTERED_ONLY
,
1479 "alias only unregistered addresses",
1480 "unregistered_only",
1483 { PacketAliasOption
,
1491 { PacketAliasOption
,
1492 PKT_ALIAS_PROXY_ONLY
,
1499 { PacketAliasOption
,
1503 "operate in reverse mode",
1507 { PacketAliasOption
,
1508 PKT_ALIAS_DENY_INCOMING
,
1511 "allow incoming connections",
1515 { PacketAliasOption
,
1516 PKT_ALIAS_USE_SOCKETS
,
1519 "use sockets to inhibit port conflict",
1523 { PacketAliasOption
,
1524 PKT_ALIAS_SAME_PORTS
,
1527 "try to keep original port numbers for connections",
1535 "verbose mode, dump packet information",
1543 "dynamic mode, automatically detect interface address changes",
1551 "enable TCP MSS clamping",
1558 "number|service_name",
1559 "set port for incoming packets",
1566 "number|service_name",
1567 "set port for outgoing packets",
1574 "number|service_name",
1575 "set port (defaults to natd/divert)",
1583 "address to use for aliasing",
1591 "address to use for incoming sessions",
1599 "take aliasing address from interface",
1606 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1608 "add transparent proxying / destination NAT",
1615 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range"
1616 " [remote_addr[:remote_port_range]]",
1617 "redirect a port (or ports) for incoming traffic",
1624 "proto local_addr [public_addr] [remote_addr]",
1625 "redirect packets of a given proto",
1632 "local_addr[,...] public_addr",
1633 "define mapping between local and public addresses",
1641 "read options from configuration file",
1649 "enable logging of denied incoming packets",
1657 "name of syslog facility to use for logging",
1665 "punch holes in the firewall for incoming FTP/IRC DCC connections",
1674 "enable NATPortMap protocol",
1675 "enable_natportmap",
1682 "take aliasing address to interface",
1683 "natportmap_interface",
1689 static void ParseOption (const char* option
, const char* parms
)
1692 struct OptionInfo
* info
;
1697 const char* strValue
;
1698 struct in_addr addrValue
;
1701 CODE
* fac_record
= NULL
;
1703 * Find option from table.
1705 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1706 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1708 if (!strcmp (info
->name
, option
))
1711 if (info
->shortName
)
1712 if (!strcmp (info
->shortName
, option
))
1718 warnx ("unknown option %s", option
);
1729 switch (info
->parm
) {
1734 if (!strcmp (parms
, "yes"))
1737 if (!strcmp (parms
, "no"))
1740 errx (1, "%s needs yes/no parameter", option
);
1745 errx (1, "%s needs service name or "
1746 "port number parameter",
1749 uNumValue
= StrToPort (parms
, "divert");
1754 numValue
= strtol (parms
, &end
, 10);
1759 errx (1, "%s needs numeric parameter", option
);
1765 errx (1, "%s needs parameter", option
);
1770 errx (1, "%s does not take parameters", option
);
1775 errx (1, "%s needs address/host parameter", option
);
1777 StrToAddr (parms
, &addrValue
);
1781 switch (info
->type
) {
1782 case PacketAliasOption
:
1784 aliasValue
= yesNoValue
? info
->packetAliasOpt
: 0;
1785 PacketAliasSetMode (aliasValue
, info
->packetAliasOpt
);
1789 verbose
= yesNoValue
;
1793 dynamicMode
= yesNoValue
;
1797 clampMSS
= yesNoValue
;
1805 outPort
= uNumValue
;
1809 inOutPort
= uNumValue
;
1813 memcpy (&aliasAddr
, &addrValue
, sizeof (struct in_addr
));
1817 PacketAliasSetTarget(addrValue
);
1821 SetupPortRedirect (strValue
);
1825 SetupProtoRedirect(strValue
);
1828 case RedirectAddress
:
1829 SetupAddressRedirect (strValue
);
1833 PacketAliasProxyRule (strValue
);
1840 ifName
= strdup (strValue
);
1844 ReadConfigFile (strValue
);
1853 fac_record
= facilitynames
;
1854 while (fac_record
->c_name
!= NULL
) {
1856 if (!strcmp (fac_record
->c_name
, strValue
)) {
1858 logFacility
= fac_record
->c_val
;
1866 if(fac_record
->c_name
== NULL
)
1867 errx(1, "Unknown log facility name: %s", strValue
);
1872 SetupPunchFW(strValue
);
1877 enable_natportmap
= yesNoValue
;
1881 case ToInterfaceName
:
1883 if (forwardedinterfacename
!= NULL
)
1885 if ( realloc(forwardedinterfacename
, (numofinterfaces
+1) * sizeof(*forwardedinterfacename
)) == NULL
){
1886 printf("realloc error, cannot allocate memory for fowarded interface name.\n");
1891 if ( (forwardedinterfacename
= malloc( sizeof(*forwardedinterfacename
) )) == NULL
){
1892 printf("malloc error, cannot allocate memory for fowarded interface name.\n");
1897 forwardedinterfacename
[numofinterfaces
] = strdup(strValue
);
1908 void ReadConfigFile (const char* fileName
)
1916 file
= fopen (fileName
, "r");
1918 err(1, "cannot open config file %s", fileName
);
1920 while ((buf
= fgetln(file
, &len
)) != NULL
) {
1921 if (buf
[len
- 1] == '\n')
1922 buf
[len
- 1] = '\0';
1924 errx(1, "config file format error: "
1925 "last line should end with newline");
1928 * Check for comments, strip off trailing spaces.
1930 if ((ptr
= strchr(buf
, '#')))
1932 for (ptr
= buf
; isspace(*ptr
); ++ptr
)
1936 for (p
= strchr(buf
, '\0'); isspace(*--p
);)
1941 * Extract option name.
1944 while (*ptr
&& !isspace (*ptr
))
1953 * Skip white space between name and parms.
1955 while (*ptr
&& isspace (*ptr
))
1958 ParseOption (option
, *ptr
? ptr
: NULL
);
1964 static void Usage ()
1968 struct OptionInfo
* info
;
1970 fprintf (stderr
, "Recognized options:\n\n");
1972 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1973 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1975 fprintf (stderr
, "-%-20s %s\n", info
->name
,
1976 info
->parmDescription
);
1978 if (info
->shortName
)
1979 fprintf (stderr
, "-%-20s %s\n", info
->shortName
,
1980 info
->parmDescription
);
1982 fprintf (stderr
, " %s\n\n", info
->description
);
1988 void SetupPortRedirect (const char* parms
)
1993 struct in_addr localAddr
;
1994 struct in_addr publicAddr
;
1995 struct in_addr remoteAddr
;
1996 port_range portRange
;
1997 u_short localPort
= 0;
1998 u_short publicPort
= 0;
1999 u_short remotePort
= 0;
2000 u_short numLocalPorts
= 0;
2001 u_short numPublicPorts
= 0;
2002 u_short numRemotePorts
= 0;
2007 struct alias_link
*link
= NULL
;
2009 strcpy (buf
, parms
);
2013 protoName
= strtok (buf
, " \t");
2015 errx (1, "redirect_port: missing protocol");
2017 proto
= StrToProto (protoName
);
2019 * Extract local address.
2021 ptr
= strtok (NULL
, " \t");
2023 errx (1, "redirect_port: missing local address");
2025 separator
= strchr(ptr
, ',');
2026 if (separator
) { /* LSNAT redirection syntax. */
2027 localAddr
.s_addr
= INADDR_NONE
;
2032 if ( StrToAddrAndPortRange (ptr
, &localAddr
, protoName
, &portRange
) != 0 )
2033 errx (1, "redirect_port: invalid local port range");
2035 localPort
= GETLOPORT(portRange
);
2036 numLocalPorts
= GETNUMPORTS(portRange
);
2041 * Extract public port and optionally address.
2043 ptr
= strtok (NULL
, " \t");
2045 errx (1, "redirect_port: missing public port");
2047 separator
= strchr (ptr
, ':');
2049 if (StrToAddrAndPortRange (ptr
, &publicAddr
, protoName
, &portRange
) != 0 )
2050 errx (1, "redirect_port: invalid public port range");
2053 publicAddr
.s_addr
= INADDR_ANY
;
2054 if (StrToPortRange (ptr
, protoName
, &portRange
) != 0)
2055 errx (1, "redirect_port: invalid public port range");
2058 publicPort
= GETLOPORT(portRange
);
2059 numPublicPorts
= GETNUMPORTS(portRange
);
2062 * Extract remote address and optionally port.
2064 ptr
= strtok (NULL
, " \t");
2066 separator
= strchr (ptr
, ':');
2068 if (StrToAddrAndPortRange (ptr
, &remoteAddr
, protoName
, &portRange
) != 0)
2069 errx (1, "redirect_port: invalid remote port range");
2071 SETLOPORT(portRange
, 0);
2072 SETNUMPORTS(portRange
, 1);
2073 StrToAddr (ptr
, &remoteAddr
);
2077 SETLOPORT(portRange
, 0);
2078 SETNUMPORTS(portRange
, 1);
2079 remoteAddr
.s_addr
= INADDR_ANY
;
2082 remotePort
= GETLOPORT(portRange
);
2083 numRemotePorts
= GETNUMPORTS(portRange
);
2086 * Make sure port ranges match up, then add the redirect ports.
2088 if (numLocalPorts
!= numPublicPorts
)
2089 errx (1, "redirect_port: port ranges must be equal in size");
2091 /* Remote port range is allowed to be '0' which means all ports. */
2092 if (numRemotePorts
!= numLocalPorts
&& (numRemotePorts
!= 1 || remotePort
!= 0))
2093 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
2095 for (i
= 0 ; i
< numPublicPorts
; ++i
) {
2096 /* If remotePort is all ports, set it to 0. */
2097 u_short remotePortCopy
= remotePort
+ i
;
2098 if (numRemotePorts
== 1 && remotePort
== 0)
2101 link
= PacketAliasRedirectPort (localAddr
,
2102 htons(localPort
+ i
),
2104 htons(remotePortCopy
),
2106 htons(publicPort
+ i
),
2111 * Setup LSNAT server pool.
2113 if (serverPool
!= NULL
&& link
!= NULL
) {
2114 ptr
= strtok(serverPool
, ",");
2115 while (ptr
!= NULL
) {
2116 if (StrToAddrAndPortRange(ptr
, &localAddr
, protoName
, &portRange
) != 0)
2117 errx(1, "redirect_port: invalid local port range");
2119 localPort
= GETLOPORT(portRange
);
2120 if (GETNUMPORTS(portRange
) != 1)
2121 errx(1, "redirect_port: local port must be single in this context");
2122 PacketAliasAddServer(link
, localAddr
, htons(localPort
));
2123 ptr
= strtok(NULL
, ",");
2129 SetupProtoRedirect(const char* parms
)
2133 struct in_addr localAddr
;
2134 struct in_addr publicAddr
;
2135 struct in_addr remoteAddr
;
2138 struct protoent
*protoent
;
2140 strcpy (buf
, parms
);
2144 protoName
= strtok(buf
, " \t");
2146 errx(1, "redirect_proto: missing protocol");
2148 protoent
= getprotobyname(protoName
);
2149 if (protoent
== NULL
)
2150 errx(1, "redirect_proto: unknown protocol %s", protoName
);
2152 proto
= protoent
->p_proto
;
2154 * Extract local address.
2156 ptr
= strtok(NULL
, " \t");
2158 errx(1, "redirect_proto: missing local address");
2160 StrToAddr(ptr
, &localAddr
);
2162 * Extract optional public address.
2164 ptr
= strtok(NULL
, " \t");
2166 StrToAddr(ptr
, &publicAddr
);
2168 publicAddr
.s_addr
= INADDR_ANY
;
2170 * Extract optional remote address.
2172 ptr
= strtok(NULL
, " \t");
2174 StrToAddr(ptr
, &remoteAddr
);
2176 remoteAddr
.s_addr
= INADDR_ANY
;
2178 * Create aliasing link.
2180 (void)PacketAliasRedirectProto(localAddr
, remoteAddr
, publicAddr
,
2184 void SetupAddressRedirect (const char* parms
)
2189 struct in_addr localAddr
;
2190 struct in_addr publicAddr
;
2192 struct alias_link
*link
;
2194 strcpy (buf
, parms
);
2196 * Extract local address.
2198 ptr
= strtok (buf
, " \t");
2200 errx (1, "redirect_address: missing local address");
2202 separator
= strchr(ptr
, ',');
2203 if (separator
) { /* LSNAT redirection syntax. */
2204 localAddr
.s_addr
= INADDR_NONE
;
2207 StrToAddr (ptr
, &localAddr
);
2211 * Extract public address.
2213 ptr
= strtok (NULL
, " \t");
2215 errx (1, "redirect_address: missing public address");
2217 StrToAddr (ptr
, &publicAddr
);
2218 link
= PacketAliasRedirectAddr(localAddr
, publicAddr
);
2221 * Setup LSNAT server pool.
2223 if (serverPool
!= NULL
&& link
!= NULL
) {
2224 ptr
= strtok(serverPool
, ",");
2225 while (ptr
!= NULL
) {
2226 StrToAddr(ptr
, &localAddr
);
2227 PacketAliasAddServer(link
, localAddr
, htons(~0));
2228 ptr
= strtok(NULL
, ",");
2233 void StrToAddr (const char* str
, struct in_addr
* addr
)
2237 if (inet_aton (str
, addr
))
2240 hp
= gethostbyname (str
);
2242 errx (1, "unknown host %s", str
);
2244 memcpy (addr
, hp
->h_addr
, sizeof (struct in_addr
));
2247 u_short
StrToPort (const char* str
, const char* proto
)
2253 port
= strtol (str
, &end
, 10);
2255 return htons (port
);
2257 sp
= getservbyname (str
, proto
);
2259 errx (1, "unknown service %s/%s", str
, proto
);
2264 int StrToPortRange (const char* str
, const char* proto
, port_range
*portRange
)
2272 /* First see if this is a service, return corresponding port if so. */
2273 sp
= getservbyname (str
,proto
);
2275 SETLOPORT(*portRange
, ntohs(sp
->s_port
));
2276 SETNUMPORTS(*portRange
, 1);
2280 /* Not a service, see if it's a single port or port range. */
2281 sep
= strchr (str
, '-');
2283 SETLOPORT(*portRange
, strtol(str
, &end
, 10));
2286 SETNUMPORTS(*portRange
, 1);
2290 /* Error in port range field. */
2291 errx (1, "unknown service %s/%s", str
, proto
);
2294 /* Port range, get the values and sanity check. */
2295 sscanf (str
, "%hu-%hu", &loPort
, &hiPort
);
2296 SETLOPORT(*portRange
, loPort
);
2297 SETNUMPORTS(*portRange
, 0); /* Error by default */
2298 if (loPort
<= hiPort
)
2299 SETNUMPORTS(*portRange
, hiPort
- loPort
+ 1);
2301 if (GETNUMPORTS(*portRange
) == 0)
2302 errx (1, "invalid port range %s", str
);
2308 int StrToProto (const char* str
)
2310 if (!strcmp (str
, "tcp"))
2313 if (!strcmp (str
, "udp"))
2316 errx (1, "unknown protocol %s. Expected tcp or udp", str
);
2319 int StrToAddrAndPortRange (const char* str
, struct in_addr
* addr
, char* proto
, port_range
*portRange
)
2323 ptr
= strchr (str
, ':');
2325 errx (1, "%s is missing port number", str
);
2330 StrToAddr (str
, addr
);
2331 return StrToPortRange (ptr
, proto
, portRange
);
2335 SetupPunchFW(const char *strValue
)
2337 unsigned int base
, num
;
2339 if (sscanf(strValue
, "%u:%u", &base
, &num
) != 2)
2340 errx(1, "punch_fw: basenumber:count parameter required");
2342 PacketAliasSetFWBase(base
, num
);
2343 (void)PacketAliasSetMode(PKT_ALIAS_PUNCH_FW
, PKT_ALIAS_PUNCH_FW
);