2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * natd - Network Address Translation Daemon for FreeBSD.
26 * This software is provided free of charge, with no
27 * warranty of any kind, either expressed or implied.
28 * Use at your own risk.
30 * You may copy, modify and distribute this software (natd.c) freely.
32 * Ari Suutari <suutari@iki.fi>
35 * $FreeBSD: src/sbin/natd/natd.c,v 1.25.2.3 2000/07/11 20:00:57 ru Exp $
40 #include <sys/types.h>
41 #include <sys/socket.h>
44 #include <sys/sysctl.h>
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/ip.h>
50 #include <netinet/tcp.h>
51 #include <netinet/udp.h>
52 #include <netinet/ip_icmp.h>
54 #include <net/if_dl.h>
55 #include <net/route.h>
56 #include <arpa/inet.h>
69 #include <mach/mach_time.h>
70 #include <mach/clock_types.h>
75 * Default values for input and output
76 * divert socket ports.
79 #define DEFAULT_SERVICE "natd"
82 * Definition of a port range, and macros to deal with values.
83 * FORMAT: HI 16-bits == first port in range, 0 == all ports.
84 * LO 16-bits == number of ports in range
85 * NOTES: - Port values are not stored in network byte order.
88 typedef u_long port_range
;
90 #define GETLOPORT(x) ((x) >> 0x10)
91 #define GETNUMPORTS(x) ((x) & 0x0000ffff)
92 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
94 /* Set y to be the low-port value in port_range variable x. */
95 #define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
97 /* Set y to be the number of ports in port_range variable x. */
98 #define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
101 * Function prototypes.
104 static void DoAliasing (int fd
, int direction
);
105 static void DaemonMode (void);
106 static void HandleRoutingInfo (int fd
);
107 static void Usage (void);
108 static char* FormatPacket (struct ip
*);
109 static void PrintPacket (struct ip
*);
110 static void SyslogPacket (struct ip
*, int priority
, const char *label
);
111 static void SetAliasAddressFromIfName (const char *ifName
);
112 static void InitiateShutdown (int);
113 static void Shutdown (int);
114 static void RefreshAddr (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
;
160 #define NATPMPORT 5351
162 #define NATPMVERSION 0
163 #define PUBLICADDRREQ 0
166 #define MAPUDPTCPREQ 3
167 #define SERVERREPLYOP 128
168 #define PUBLICADDRRLY SERVERREPLYOP+PUBLICADDRREQ
171 #define NOTSUPPORTEDVERSION 1
172 #define NOTAUTHORIZED 2
173 #define NETWORKFAILURE 3
174 #define OUTOFRESOURCES 4
175 #define UNSUPPORTEDOPCODE 5
177 #define TIMER_RATE 250
181 typedef struct stdportmaprequest
{
183 unsigned char opcode
;
184 unsigned short result
;
189 typedef struct publicaddrreply
{
191 unsigned char opcode
;
192 unsigned short result
;
196 typedef struct publicportreq
{
198 unsigned char opcode
;
199 unsigned short result
;
201 unsigned short privateport
;
202 unsigned short publicport
;
203 int lifetime
; /* in second */
205 typedef struct stderrreply
{
207 unsigned char opcode
;
208 unsigned short result
;
213 static int enable_natportmap
= 0;
214 static struct in_addr lastassignaliasAddr
;
215 static int portmapSock
= -1;
216 static struct in_addr
*forwardedinterfaceaddr
;
217 static char **forwardedinterfacename
;
218 static int numofinterfaces
= 0; /* has to be at least one */
219 static u_short natPMPport
;
220 static int numoftries
=MAXRETRY
;
221 static struct itimerval itval
;
222 static int Natdtimerset
= 0;
223 static double secdivisor
;
226 static void HandlePortMap( int fd
);
227 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
);
228 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
);
229 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*reply
, int publicport
);
230 static void Doubletime( struct timeval
*tvp
);
231 static void Stoptimer();
232 static void Natdtimer();
233 static void SendPortMapMulti( );
234 static void NotifyPublicAddress();
235 static void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
);
236 static void NatPortMapPInit();
237 static u_short
get_natportmap_port(void);
239 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
);
243 int main (int argc
, char** argv
)
249 struct sockaddr_in addr
;
254 * Initialize packet aliasing software.
255 * Done already here to be able to alter option bits
256 * during command line and configuration file processing.
271 aliasAddr
.s_addr
= INADDR_NONE
;
273 lastassignaliasAddr
.s_addr
= INADDR_NONE
;
278 logFacility
= LOG_DAEMON
;
280 * Mark packet buffer empty.
283 packetDirection
= DONT_KNOW
;
285 ParseArgs (argc
, argv
);
287 * Open syslog channel.
289 openlog ("natd", LOG_CONS
| LOG_PID
| (verbose
? LOG_PERROR
: 0),
292 * Check that valid aliasing address has been given.
294 if (aliasAddr
.s_addr
== INADDR_NONE
&& ifName
== NULL
)
295 errx (1, "aliasing address not given");
298 * Check that valid port number is known.
300 if (inPort
!= 0 || outPort
!= 0)
301 if (inPort
== 0 || outPort
== 0)
302 errx (1, "both input and output ports are required");
304 if (inPort
== 0 && outPort
== 0 && inOutPort
== 0)
305 ParseOption ("port", DEFAULT_SERVICE
);
308 * Check if ignored packets should be dropped.
310 dropIgnoredIncoming
= PacketAliasSetMode (0, 0);
311 dropIgnoredIncoming
&= PKT_ALIAS_DENY_INCOMING
;
313 * Create divert sockets. Use only one socket if -p was specified
314 * on command line. Otherwise, create separate sockets for
315 * outgoing and incoming connnections.
319 divertInOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
320 if (divertInOut
== -1)
321 Quit ("Unable to create divert socket.");
329 addr
.sin_family
= AF_INET
;
330 addr
.sin_addr
.s_addr
= INADDR_ANY
;
331 addr
.sin_port
= inOutPort
;
333 if (bind (divertInOut
,
334 (struct sockaddr
*) &addr
,
336 Quit ("Unable to bind divert socket.");
340 divertIn
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
342 Quit ("Unable to create incoming divert socket.");
344 divertOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
346 Quit ("Unable to create outgoing divert socket.");
351 * Bind divert sockets.
354 addr
.sin_family
= AF_INET
;
355 addr
.sin_addr
.s_addr
= INADDR_ANY
;
356 addr
.sin_port
= inPort
;
359 (struct sockaddr
*) &addr
,
361 Quit ("Unable to bind incoming divert socket.");
363 addr
.sin_family
= AF_INET
;
364 addr
.sin_addr
.s_addr
= INADDR_ANY
;
365 addr
.sin_port
= outPort
;
368 (struct sockaddr
*) &addr
,
370 Quit ("Unable to bind outgoing divert socket.");
373 * Create routing socket if interface name specified and in dynamic mode.
379 routeSock
= socket (PF_ROUTE
, SOCK_RAW
, 0);
381 Quit ("Unable to create routing info socket.");
386 SetAliasAddressFromIfName (ifName
);
390 * Create socket for sending ICMP messages.
392 icmpSock
= socket (AF_INET
, SOCK_RAW
, IPPROTO_ICMP
);
394 Quit ("Unable to create ICMP socket.");
397 * And disable reads for the socket, otherwise it slowly fills
398 * up with received icmps which we do not use.
400 shutdown(icmpSock
, SHUT_RD
);
404 if ( enable_natportmap
)
406 /* create socket to listen for port mapping */
407 portmapSock
= socket( AF_INET
, SOCK_DGRAM
, 0);
408 if ( portmapSock
!= -1 )
410 natPMPport
= get_natportmap_port();
411 addr
.sin_family
= AF_INET
;
412 addr
.sin_addr
.s_addr
= INADDR_ANY
;
413 addr
.sin_port
= NATPMPORT
;
415 if (bind ( portmapSock
,
416 (struct sockaddr
*) &addr
,
418 printf("Binding to NATPM port failed!\n");
420 /* NATPORTMAPP initial set up */
423 if ( !Natdtimerset
){
425 signal(SIGALRM
, Natdtimer
);
430 * Become a daemon unless verbose mode was requested.
435 * Catch signals to manage shutdown and
436 * refresh of interface address.
438 siginterrupt(SIGTERM
, 1);
439 siginterrupt(SIGHUP
, 1);
440 signal (SIGTERM
, InitiateShutdown
);
441 signal (SIGHUP
, RefreshAddr
);
443 * Set alias address if it has been given.
445 if (aliasAddr
.s_addr
!= INADDR_NONE
)
447 PacketAliasSetAddress (aliasAddr
);
449 if ( (enable_natportmap
) && (aliasAddr
.s_addr
!= lastassignaliasAddr
.s_addr
) ){
450 lastassignaliasAddr
.s_addr
= aliasAddr
.s_addr
;
451 NotifyPublicAddress();
456 * We need largest descriptor number for select.
461 if (divertIn
> fdMax
)
464 if (divertOut
> fdMax
)
467 if (divertInOut
> fdMax
)
470 if (routeSock
> fdMax
)
474 if ( portmapSock
> fdMax
)
481 if (divertInOut
!= -1 && !ifName
&& packetSock
== -1) {
483 * When using only one socket, just call
484 * DoAliasing repeatedly to process packets.
486 DoAliasing (divertInOut
, DONT_KNOW
);
490 * Build read mask from socket descriptors to select.
493 FD_ZERO (&writeMask
);
496 * If there is unsent packet in buffer, use select
497 * to check when socket comes writable again.
499 if (packetSock
!= -1) {
501 FD_SET (packetSock
, &writeMask
);
505 * No unsent packet exists - safe to check if
506 * new ones are available.
509 FD_SET (divertIn
, &readMask
);
512 FD_SET (divertOut
, &readMask
);
514 if (divertInOut
!= -1)
515 FD_SET (divertInOut
, &readMask
);
518 * Routing info is processed always.
521 FD_SET (routeSock
, &readMask
);
523 if ( portmapSock
!= -1 )
524 FD_SET (portmapSock
, &readMask
);
526 if (select (fdMax
+ 1,
535 Quit ("Select failed.");
538 if (packetSock
!= -1)
539 if (FD_ISSET (packetSock
, &writeMask
))
540 FlushPacketBuffer (packetSock
);
543 if (FD_ISSET (divertIn
, &readMask
))
544 DoAliasing (divertIn
, INPUT
);
547 if (FD_ISSET (divertOut
, &readMask
))
548 DoAliasing (divertOut
, OUTPUT
);
550 if (divertInOut
!= -1)
551 if (FD_ISSET (divertInOut
, &readMask
))
552 DoAliasing (divertInOut
, DONT_KNOW
);
555 if (FD_ISSET (routeSock
, &readMask
))
556 HandleRoutingInfo (routeSock
);
558 if ( portmapSock
!= -1)
559 if (FD_ISSET (portmapSock
, &readMask
))
560 HandlePortMap( portmapSock
);
570 static void DaemonMode ()
577 pidFile
= fopen (PIDFILE
, "w");
580 fprintf (pidFile
, "%d\n", getpid ());
585 static void ParseArgs (int argc
, char** argv
)
590 int len
; /* bounds checking */
592 for (arg
= 1; arg
< argc
; arg
++) {
597 warnx ("invalid option %s", opt
);
604 while (arg
< argc
- 1) {
606 if (argv
[arg
+ 1][0] == '-')
610 strncat (parmBuf
, " ", sizeof(parmBuf
) - (len
+ 1));
611 len
+= strlen(parmBuf
+ len
);
615 strncat (parmBuf
, argv
[arg
], sizeof(parmBuf
) - (len
+ 1));
616 len
+= strlen(parmBuf
+ len
);
620 ParseOption (opt
+ 1, (len
? parmBuf
: NULL
));
625 static void DoAliasing (int fd
, int direction
)
633 if (assignAliasAddr
) {
635 SetAliasAddressFromIfName (ifName
);
639 * Get packet from socket.
641 addrSize
= sizeof packetAddr
;
642 origBytes
= recvfrom (fd
,
646 (struct sockaddr
*) &packetAddr
,
649 if (origBytes
== -1) {
652 Warn ("read from divert socket failed");
657 * This is a IP packet.
659 ip
= (struct ip
*) packetBuf
;
660 if (direction
== DONT_KNOW
) {
661 if (packetAddr
.sin_addr
.s_addr
== INADDR_ANY
)
669 * Print packet direction and protocol type.
671 printf (direction
== OUTPUT
? "Out " : "In ");
687 printf ("[%d] ", ip
->ip_p
);
696 if (direction
== OUTPUT
) {
698 * Outgoing packets. Do aliasing.
700 PacketAliasOut (packetBuf
, IP_MAXPACKET
);
707 status
= PacketAliasIn (packetBuf
, IP_MAXPACKET
);
708 if (status
== PKT_ALIAS_IGNORED
&&
709 dropIgnoredIncoming
) {
712 printf (" dropped.\n");
715 SyslogPacket (ip
, LOG_WARNING
, "denied");
721 * Length might have changed during aliasing.
723 bytes
= ntohs (ip
->ip_len
);
725 * Update alias overhead size for outgoing packets.
727 if (direction
== OUTPUT
&&
728 bytes
- origBytes
> aliasOverhead
)
729 aliasOverhead
= bytes
- origBytes
;
734 * Print addresses after aliasing.
736 printf (" aliased to\n");
744 packetDirection
= direction
;
746 FlushPacketBuffer (fd
);
749 static void FlushPacketBuffer (int fd
)
754 * Put packet back for processing.
760 (struct sockaddr
*) &packetAddr
,
763 if (wrote
!= packetLen
) {
765 * If buffer space is not available,
766 * just return. Main loop will take care of
767 * retrying send when space becomes available.
769 if (errno
== ENOBUFS
)
772 if (errno
== EMSGSIZE
) {
774 if (packetDirection
== OUTPUT
&&
776 SendNeedFragIcmp (icmpSock
,
777 (struct ip
*) packetBuf
,
778 ifMTU
- aliasOverhead
);
782 sprintf (msgBuf
, "failed to write packet back");
790 static void HandleRoutingInfo (int fd
)
793 struct if_msghdr ifMsg
;
795 * Get packet from socket.
797 bytes
= read (fd
, &ifMsg
, sizeof ifMsg
);
800 Warn ("read from routing socket failed");
804 if (ifMsg
.ifm_version
!= RTM_VERSION
) {
806 Warn ("unexpected packet read from routing socket");
811 printf ("Routing message %#x received.\n", ifMsg
.ifm_type
);
813 if ((ifMsg
.ifm_type
== RTM_NEWADDR
|| ifMsg
.ifm_type
== RTM_IFINFO
) &&
814 ifMsg
.ifm_index
== ifIndex
) {
816 printf("Interface address/MTU has probably changed.\n");
825 struct mach_timebase_info info
;
827 (void) mach_timebase_info (&info
);
829 secdivisor
= ( (double)info
.denom
/ (double)info
.numer
) * 1000;
833 unsigned int getuptime()
836 unsigned long epochtime
;
838 now
= mach_absolute_time();
839 epochtime
= (now
/ secdivisor
) /USEC_PER_SEC
;
844 /* return NATPORTMAP port defined in /etc/servcies if there's one, else use NATPMPORT */
845 static u_short
get_natportmap_port(void)
849 ent
= getservbyname( "natportmap", "udp" );
851 return( ent
->s_port
);
856 /* set up neccessary info for doing NatPortMapP */
857 static void NatPortMapPInit()
860 struct ifaddrs
*ifap
, *ifa
;
862 forwardedinterfaceaddr
= (struct in_addr
*)
863 malloc(numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
864 bzero(forwardedinterfaceaddr
,
865 numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
866 /* interface address hasn't been set up, get interface address */
868 for ( ifa
= ifap
; ifa
; ifa
=ifa
->ifa_next
)
870 struct sockaddr_in
* a
;
871 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
875 a
= (struct sockaddr_in
*)ifa
->ifa_addr
;
876 for ( i
= 0; i
< numofinterfaces
; i
++ )
878 if (strcmp(ifa
->ifa_name
, forwardedinterfacename
[i
]))
882 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
884 /* copy the first IP address */
885 forwardedinterfaceaddr
[i
] = a
->sin_addr
;
894 /* SendPortMapResponse */
895 /* send generic reponses to NATPORTMAP requests */
896 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
)
901 reply
.version
= NATPMVERSION
;
902 reply
.opcode
= origopcode
+ SERVERREPLYOP
;
903 reply
.result
= result
;
904 reply
.epoch
= getuptime();
905 bytes
= sendto( fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
906 if ( bytes
!= sizeof(reply
) )
907 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
910 /* SendPublicAddress */
911 /* return public address to requestor */
912 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
)
915 publicaddrreply reply
;
918 reply
.version
= NATPMVERSION
;
919 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
920 reply
.result
= SUCCESS
;
921 reply
.addr
= lastassignaliasAddr
;
922 reply
.epoch
= getuptime();
924 bytes
= sendto (fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
925 if ( bytes
!= sizeof(reply
) )
926 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
929 /* SendPublicPortResponse */
930 /* response for portmap request and portmap removal request */
931 /* publicport <= 0 means error */
932 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*reply
, int publicport
)
937 reply
->version
= NATPMVERSION
;
938 reply
->opcode
= SERVERREPLYOP
+ reply
->opcode
;
939 if ( publicport
<= 0)
940 /* error in port mapping */
941 reply
->result
= OUTOFRESOURCES
;
943 reply
->result
= SUCCESS
;
944 reply
->epoch
= getuptime();
946 if ( reply
->lifetime
) /* not delete mapping */
947 reply
->publicport
= publicport
;
948 bytes
= sendto (fd
, (void*)reply
, sizeof(publicportreq
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
949 if ( bytes
!= sizeof(publicportreq
) )
950 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
->opcode
);
953 /* SendPortMapMulti */
954 /* send multicast to local network for new alias address */
955 static void SendPortMapMulti()
958 publicaddrreply reply
;
960 struct sockaddr_in multiaddr
;
964 #define LOCALGROUP "224.0.0.1"
966 memset(&multiaddr
,0,sizeof(struct sockaddr_in
));
967 multiaddr
.sin_family
=AF_INET
;
968 multiaddr
.sin_addr
.s_addr
=inet_addr(LOCALGROUP
);
969 multiaddr
.sin_port
=htons(NATPMPORT
);
970 reply
.version
= NATPMVERSION
;
971 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
972 reply
.result
= SUCCESS
;
973 reply
.addr
= lastassignaliasAddr
;
976 /* send multicast to all forwarded interfaces */
977 for ( i
= 0; i
< numofinterfaces
; i
++)
979 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
983 multisock
= socket( AF_INET
, SOCK_DGRAM
, 0);
985 if ( multisock
== -1 )
987 printf("cannot get socket for sending multicast\n");
990 if (setsockopt(multisock
, IPPROTO_IP
, IP_MULTICAST_IF
, &forwardedinterfaceaddr
[i
], sizeof(struct in_addr
)) < 0)
992 printf("setsockopt failed\n");
996 bytes
= sendto (multisock
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)&multiaddr
, sizeof(multiaddr
));
997 if ( bytes
!= sizeof(reply
) )
998 printf( "PORTMAP::problem sending multicast alias address - opcode %d\n", reply
.opcode
);
1004 /* double the time value */
1005 static void Doubletime( struct timeval
*tvp
)
1012 if (tvp
->tv_usec
>= 1000000) {
1013 tvp
->tv_sec
+= tvp
->tv_usec
/ 1000000;
1014 tvp
->tv_usec
= tvp
->tv_usec
% 1000000;
1018 /* stop running natd timer */
1019 static void Stoptimer()
1021 itval
.it_value
.tv_usec
= 0;
1022 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1023 printf( "setitimer err: %d\n", errno
);
1027 /* timer routine to send new public IP address */
1028 static void Natdtimer()
1030 if ( !enable_natportmap
)
1035 if ( numoftries
< MAXRETRY
){
1036 Doubletime( &itval
.it_value
);
1037 itval
.it_interval
= itval
.it_value
;
1038 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1039 printf( "setitimer err: %d\n", errno
);
1049 /* NotifyPublicAddress */
1050 /* Advertise new public address */
1051 static void NotifyPublicAddress()
1053 if ( numoftries
< MAXRETRY
)
1055 /* there is an old timer running, cancel it */
1058 /* send up new timer */
1061 itval
.it_value
.tv_sec
= 0;
1062 itval
.it_value
.tv_usec
= TIMER_RATE
;
1063 itval
.it_interval
.tv_sec
= 0;
1064 itval
.it_interval
.tv_usec
= TIMER_RATE
;
1065 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1066 printf( "setitimer err: %d\n", errno
);
1071 /* find/add/remove port mapping from alias manager */
1072 void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
)
1074 u_char proto
= IPPROTO_TCP
;
1077 if ( req
->opcode
== MAPUDPREQ
)
1078 proto
= IPPROTO_UDP
;
1079 if ( req
->lifetime
== 0)
1081 /* remove port mapping */
1082 if ( !FindAliasPortOut( clientaddr
->sin_addr
, lastassignaliasAddr
, req
->privateport
, req
->publicport
, proto
, req
->lifetime
, 0))
1083 /* FindAliasPortOut returns no error, port successfully removed, return no error response to client */
1084 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, 1 );
1086 /* deleting port fails, return error */
1087 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, -1 );
1091 /* look for port mapping - public port is ignored in this case */
1092 /* create port mapping - map provided public port to private port if public port is not 0 */
1093 aliasport
= FindAliasPortOut( clientaddr
->sin_addr
, lastassignaliasAddr
, req
->privateport
, req
->publicport
, proto
, req
->lifetime
, 1);
1094 /* aliasport should be non zero if mapping is successfully, else -1 is returned, alias port shouldn't be zero???? */
1095 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, aliasport
);
1101 /* handle all packets sent to NATPORTMAP port */
1102 static void HandlePortMap( int fd
)
1104 #define MAXBUFFERSIZE 100
1106 struct sockaddr_in clientaddr
;
1108 unsigned char buffer
[MAXBUFFERSIZE
];
1110 unsigned short result
= SUCCESS
;
1111 struct stdportmaprequest
*req
;
1113 clientaddrlen
= sizeof( clientaddr
);
1114 bytes
= recvfrom( fd
, buffer
, sizeof(buffer
), 0, (struct sockaddr
*)&clientaddr
, &clientaddrlen
);
1117 printf( "Read NATPM port error\n");
1120 req
= (struct stdportmaprequest
*)buffer
;
1126 for ( i
= 0; i
<bytes
; i
++)
1128 printf("%d", buffer
[i
]);
1133 /* check client version */
1134 if ( req
->version
> NATPMVERSION
)
1135 result
= NOTSUPPORTEDVERSION
;
1136 else if ( !enable_natportmap
)
1137 /* natd wasn't launched with portmapping enabled */
1138 result
= NOTAUTHORIZED
;
1142 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, result
);
1146 switch ( req
->opcode
)
1150 SendPublicAddress(fd
, &clientaddr
, clientaddrlen
);
1158 DoPortMapping( fd
, &clientaddr
, clientaddrlen
, (publicportreq
*)req
);
1164 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, UNSUPPORTEDOPCODE
);
1172 static void PrintPacket (struct ip
* ip
)
1174 printf ("%s", FormatPacket (ip
));
1177 static void SyslogPacket (struct ip
* ip
, int priority
, const char *label
)
1179 syslog (priority
, "%s %s", label
, FormatPacket (ip
));
1182 static char* FormatPacket (struct ip
* ip
)
1184 static char buf
[256];
1185 struct tcphdr
* tcphdr
;
1186 struct udphdr
* udphdr
;
1187 struct icmp
* icmphdr
;
1191 strcpy (src
, inet_ntoa (ip
->ip_src
));
1192 strcpy (dst
, inet_ntoa (ip
->ip_dst
));
1196 tcphdr
= (struct tcphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1197 sprintf (buf
, "[TCP] %s:%d -> %s:%d",
1199 ntohs (tcphdr
->th_sport
),
1201 ntohs (tcphdr
->th_dport
));
1205 udphdr
= (struct udphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1206 sprintf (buf
, "[UDP] %s:%d -> %s:%d",
1208 ntohs (udphdr
->uh_sport
),
1210 ntohs (udphdr
->uh_dport
));
1214 icmphdr
= (struct icmp
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1215 sprintf (buf
, "[ICMP] %s -> %s %u(%u)",
1219 icmphdr
->icmp_code
);
1223 sprintf (buf
, "[%d] %s -> %s ", ip
->ip_p
, src
, dst
);
1231 SetAliasAddressFromIfName(const char *ifn
)
1235 char *buf
, *lim
, *next
;
1236 struct if_msghdr
*ifm
;
1237 struct ifa_msghdr
*ifam
;
1238 struct sockaddr_dl
*sdl
;
1239 struct sockaddr_in
*sin
;
1244 mib
[3] = AF_INET
; /* Only IP addresses please */
1245 mib
[4] = NET_RT_IFLIST
;
1246 mib
[5] = 0; /* ifIndex??? */
1248 * Get interface data.
1250 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1)
1251 err(1, "iflist-sysctl-estimate");
1252 if ((buf
= malloc(needed
)) == NULL
)
1253 errx(1, "malloc failed");
1254 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1)
1255 err(1, "iflist-sysctl-get");
1258 * Loop through interfaces until one with
1259 * given name is found. This is done to
1260 * find correct interface index for routing
1261 * message processing.
1265 while (next
< lim
) {
1266 ifm
= (struct if_msghdr
*)next
;
1267 next
+= ifm
->ifm_msglen
;
1268 if (ifm
->ifm_version
!= RTM_VERSION
) {
1270 warnx("routing message version %d "
1271 "not understood", ifm
->ifm_version
);
1274 if (ifm
->ifm_type
== RTM_IFINFO
) {
1275 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
1276 if (strlen(ifn
) == sdl
->sdl_nlen
&&
1277 strncmp(ifn
, sdl
->sdl_data
, sdl
->sdl_nlen
) == 0) {
1278 ifIndex
= ifm
->ifm_index
;
1279 ifMTU
= ifm
->ifm_data
.ifi_mtu
;
1281 PacketAliasClampMSS(ifMTU
- sizeof(struct tcphdr
) - sizeof(struct ip
));
1287 errx(1, "unknown interface name %s", ifn
);
1289 * Get interface address.
1291 if (aliasAddr
.s_addr
== INADDR_NONE
) {
1293 while (next
< lim
) {
1294 ifam
= (struct ifa_msghdr
*)next
;
1295 next
+= ifam
->ifam_msglen
;
1296 if (ifam
->ifam_version
!= RTM_VERSION
) {
1298 warnx("routing message version %d "
1299 "not understood", ifam
->ifam_version
);
1302 if (ifam
->ifam_type
!= RTM_NEWADDR
)
1304 if (ifam
->ifam_addrs
& RTA_IFA
) {
1306 char *cp
= (char *)(ifam
+ 1);
1308 #define ROUNDUP(a) \
1309 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1310 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
1312 for (i
= 1; i
< RTA_IFA
; i
<<= 1)
1313 if (ifam
->ifam_addrs
& i
)
1314 ADVANCE(cp
, (struct sockaddr
*)cp
);
1315 if (((struct sockaddr
*)cp
)->sa_family
== AF_INET
) {
1316 sin
= (struct sockaddr_in
*)cp
;
1322 errx(1, "%s: cannot get interface address", ifn
);
1324 PacketAliasSetAddress(sin
->sin_addr
);
1326 if ( (enable_natportmap
) && (sin
->sin_addr
.s_addr
!= lastassignaliasAddr
.s_addr
) )
1328 lastassignaliasAddr
.s_addr
= sin
->sin_addr
.s_addr
;
1329 /* make sure the timer handler was set before setting timer */
1330 if ( !Natdtimerset
){
1332 signal(SIGALRM
, Natdtimer
);
1334 NotifyPublicAddress();
1337 syslog(LOG_INFO
, "Aliasing to %s, mtu %d bytes",
1338 inet_ntoa(sin
->sin_addr
), ifMTU
);
1344 void Quit (const char* msg
)
1350 void Warn (const char* msg
)
1353 syslog (LOG_ALERT
, "%s (%m)", msg
);
1358 static void RefreshAddr (int sig
)
1361 assignAliasAddr
= 1;
1364 static void InitiateShutdown (int sig
)
1367 * Start timer to allow kernel gracefully
1368 * shutdown existing connections when system
1371 siginterrupt(SIGALRM
, 1);
1372 signal (SIGALRM
, Shutdown
);
1376 static void Shutdown (int sig
)
1382 * Different options recognized by this program.
1422 * Option information structure (used by ParseOption).
1430 const char* parmDescription
;
1431 const char* description
;
1433 const char* shortName
;
1437 * Table of known options.
1440 static struct OptionInfo optionTable
[] = {
1442 { PacketAliasOption
,
1443 PKT_ALIAS_UNREGISTERED_ONLY
,
1446 "alias only unregistered addresses",
1447 "unregistered_only",
1450 { PacketAliasOption
,
1458 { PacketAliasOption
,
1459 PKT_ALIAS_PROXY_ONLY
,
1466 { PacketAliasOption
,
1470 "operate in reverse mode",
1474 { PacketAliasOption
,
1475 PKT_ALIAS_DENY_INCOMING
,
1478 "allow incoming connections",
1482 { PacketAliasOption
,
1483 PKT_ALIAS_USE_SOCKETS
,
1486 "use sockets to inhibit port conflict",
1490 { PacketAliasOption
,
1491 PKT_ALIAS_SAME_PORTS
,
1494 "try to keep original port numbers for connections",
1502 "verbose mode, dump packet information",
1510 "dynamic mode, automatically detect interface address changes",
1518 "enable TCP MSS clamping",
1525 "number|service_name",
1526 "set port for incoming packets",
1533 "number|service_name",
1534 "set port for outgoing packets",
1541 "number|service_name",
1542 "set port (defaults to natd/divert)",
1550 "address to use for aliasing",
1558 "address to use for incoming sessions",
1566 "take aliasing address from interface",
1573 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1575 "add transparent proxying / destination NAT",
1582 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range"
1583 " [remote_addr[:remote_port_range]]",
1584 "redirect a port (or ports) for incoming traffic",
1591 "proto local_addr [public_addr] [remote_addr]",
1592 "redirect packets of a given proto",
1599 "local_addr[,...] public_addr",
1600 "define mapping between local and public addresses",
1608 "read options from configuration file",
1616 "enable logging of denied incoming packets",
1624 "name of syslog facility to use for logging",
1632 "punch holes in the firewall for incoming FTP/IRC DCC connections",
1641 "enable NATPortMap protocol",
1642 "enable_natportmap",
1649 "take aliasing address to interface",
1650 "natportmap_interface",
1656 static void ParseOption (const char* option
, const char* parms
)
1659 struct OptionInfo
* info
;
1664 const char* strValue
;
1665 struct in_addr addrValue
;
1668 CODE
* fac_record
= NULL
;
1670 * Find option from table.
1672 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1673 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1675 if (!strcmp (info
->name
, option
))
1678 if (info
->shortName
)
1679 if (!strcmp (info
->shortName
, option
))
1685 warnx ("unknown option %s", option
);
1696 switch (info
->parm
) {
1701 if (!strcmp (parms
, "yes"))
1704 if (!strcmp (parms
, "no"))
1707 errx (1, "%s needs yes/no parameter", option
);
1712 errx (1, "%s needs service name or "
1713 "port number parameter",
1716 uNumValue
= StrToPort (parms
, "divert");
1721 numValue
= strtol (parms
, &end
, 10);
1726 errx (1, "%s needs numeric parameter", option
);
1732 errx (1, "%s needs parameter", option
);
1737 errx (1, "%s does not take parameters", option
);
1742 errx (1, "%s needs address/host parameter", option
);
1744 StrToAddr (parms
, &addrValue
);
1748 switch (info
->type
) {
1749 case PacketAliasOption
:
1751 aliasValue
= yesNoValue
? info
->packetAliasOpt
: 0;
1752 PacketAliasSetMode (aliasValue
, info
->packetAliasOpt
);
1756 verbose
= yesNoValue
;
1760 dynamicMode
= yesNoValue
;
1764 clampMSS
= yesNoValue
;
1772 outPort
= uNumValue
;
1776 inOutPort
= uNumValue
;
1780 memcpy (&aliasAddr
, &addrValue
, sizeof (struct in_addr
));
1784 PacketAliasSetTarget(addrValue
);
1788 SetupPortRedirect (strValue
);
1792 SetupProtoRedirect(strValue
);
1795 case RedirectAddress
:
1796 SetupAddressRedirect (strValue
);
1800 PacketAliasProxyRule (strValue
);
1807 ifName
= strdup (strValue
);
1811 ReadConfigFile (strValue
);
1820 fac_record
= facilitynames
;
1821 while (fac_record
->c_name
!= NULL
) {
1823 if (!strcmp (fac_record
->c_name
, strValue
)) {
1825 logFacility
= fac_record
->c_val
;
1833 if(fac_record
->c_name
== NULL
)
1834 errx(1, "Unknown log facility name: %s", strValue
);
1839 SetupPunchFW(strValue
);
1844 enable_natportmap
= yesNoValue
;
1848 case ToInterfaceName
:
1850 if (forwardedinterfacename
!= NULL
)
1852 if ( realloc(forwardedinterfacename
, (numofinterfaces
+1) * sizeof(*forwardedinterfacename
)) == NULL
){
1853 printf("realloc error, cannot allocate memory for fowarded interface name.\n");
1858 if ( (forwardedinterfacename
= malloc( sizeof(*forwardedinterfacename
) )) == NULL
){
1859 printf("malloc error, cannot allocate memory for fowarded interface name.\n");
1864 forwardedinterfacename
[numofinterfaces
] = strdup(strValue
);
1875 void ReadConfigFile (const char* fileName
)
1883 file
= fopen (fileName
, "r");
1885 err(1, "cannot open config file %s", fileName
);
1887 while ((buf
= fgetln(file
, &len
)) != NULL
) {
1888 if (buf
[len
- 1] == '\n')
1889 buf
[len
- 1] = '\0';
1891 errx(1, "config file format error: "
1892 "last line should end with newline");
1895 * Check for comments, strip off trailing spaces.
1897 if ((ptr
= strchr(buf
, '#')))
1899 for (ptr
= buf
; isspace(*ptr
); ++ptr
)
1903 for (p
= strchr(buf
, '\0'); isspace(*--p
);)
1908 * Extract option name.
1911 while (*ptr
&& !isspace (*ptr
))
1920 * Skip white space between name and parms.
1922 while (*ptr
&& isspace (*ptr
))
1925 ParseOption (option
, *ptr
? ptr
: NULL
);
1931 static void Usage ()
1935 struct OptionInfo
* info
;
1937 fprintf (stderr
, "Recognized options:\n\n");
1939 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1940 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1942 fprintf (stderr
, "-%-20s %s\n", info
->name
,
1943 info
->parmDescription
);
1945 if (info
->shortName
)
1946 fprintf (stderr
, "-%-20s %s\n", info
->shortName
,
1947 info
->parmDescription
);
1949 fprintf (stderr
, " %s\n\n", info
->description
);
1955 void SetupPortRedirect (const char* parms
)
1960 struct in_addr localAddr
;
1961 struct in_addr publicAddr
;
1962 struct in_addr remoteAddr
;
1963 port_range portRange
;
1964 u_short localPort
= 0;
1965 u_short publicPort
= 0;
1966 u_short remotePort
= 0;
1967 u_short numLocalPorts
= 0;
1968 u_short numPublicPorts
= 0;
1969 u_short numRemotePorts
= 0;
1974 struct alias_link
*link
= NULL
;
1976 strcpy (buf
, parms
);
1980 protoName
= strtok (buf
, " \t");
1982 errx (1, "redirect_port: missing protocol");
1984 proto
= StrToProto (protoName
);
1986 * Extract local address.
1988 ptr
= strtok (NULL
, " \t");
1990 errx (1, "redirect_port: missing local address");
1992 separator
= strchr(ptr
, ',');
1993 if (separator
) { /* LSNAT redirection syntax. */
1994 localAddr
.s_addr
= INADDR_NONE
;
1999 if ( StrToAddrAndPortRange (ptr
, &localAddr
, protoName
, &portRange
) != 0 )
2000 errx (1, "redirect_port: invalid local port range");
2002 localPort
= GETLOPORT(portRange
);
2003 numLocalPorts
= GETNUMPORTS(portRange
);
2008 * Extract public port and optionally address.
2010 ptr
= strtok (NULL
, " \t");
2012 errx (1, "redirect_port: missing public port");
2014 separator
= strchr (ptr
, ':');
2016 if (StrToAddrAndPortRange (ptr
, &publicAddr
, protoName
, &portRange
) != 0 )
2017 errx (1, "redirect_port: invalid public port range");
2020 publicAddr
.s_addr
= INADDR_ANY
;
2021 if (StrToPortRange (ptr
, protoName
, &portRange
) != 0)
2022 errx (1, "redirect_port: invalid public port range");
2025 publicPort
= GETLOPORT(portRange
);
2026 numPublicPorts
= GETNUMPORTS(portRange
);
2029 * Extract remote address and optionally port.
2031 ptr
= strtok (NULL
, " \t");
2033 separator
= strchr (ptr
, ':');
2035 if (StrToAddrAndPortRange (ptr
, &remoteAddr
, protoName
, &portRange
) != 0)
2036 errx (1, "redirect_port: invalid remote port range");
2038 SETLOPORT(portRange
, 0);
2039 SETNUMPORTS(portRange
, 1);
2040 StrToAddr (ptr
, &remoteAddr
);
2044 SETLOPORT(portRange
, 0);
2045 SETNUMPORTS(portRange
, 1);
2046 remoteAddr
.s_addr
= INADDR_ANY
;
2049 remotePort
= GETLOPORT(portRange
);
2050 numRemotePorts
= GETNUMPORTS(portRange
);
2053 * Make sure port ranges match up, then add the redirect ports.
2055 if (numLocalPorts
!= numPublicPorts
)
2056 errx (1, "redirect_port: port ranges must be equal in size");
2058 /* Remote port range is allowed to be '0' which means all ports. */
2059 if (numRemotePorts
!= numLocalPorts
&& (numRemotePorts
!= 1 || remotePort
!= 0))
2060 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
2062 for (i
= 0 ; i
< numPublicPorts
; ++i
) {
2063 /* If remotePort is all ports, set it to 0. */
2064 u_short remotePortCopy
= remotePort
+ i
;
2065 if (numRemotePorts
== 1 && remotePort
== 0)
2068 link
= PacketAliasRedirectPort (localAddr
,
2069 htons(localPort
+ i
),
2071 htons(remotePortCopy
),
2073 htons(publicPort
+ i
),
2078 * Setup LSNAT server pool.
2080 if (serverPool
!= NULL
&& link
!= NULL
) {
2081 ptr
= strtok(serverPool
, ",");
2082 while (ptr
!= NULL
) {
2083 if (StrToAddrAndPortRange(ptr
, &localAddr
, protoName
, &portRange
) != 0)
2084 errx(1, "redirect_port: invalid local port range");
2086 localPort
= GETLOPORT(portRange
);
2087 if (GETNUMPORTS(portRange
) != 1)
2088 errx(1, "redirect_port: local port must be single in this context");
2089 PacketAliasAddServer(link
, localAddr
, htons(localPort
));
2090 ptr
= strtok(NULL
, ",");
2096 SetupProtoRedirect(const char* parms
)
2100 struct in_addr localAddr
;
2101 struct in_addr publicAddr
;
2102 struct in_addr remoteAddr
;
2105 struct protoent
*protoent
;
2107 strcpy (buf
, parms
);
2111 protoName
= strtok(buf
, " \t");
2113 errx(1, "redirect_proto: missing protocol");
2115 protoent
= getprotobyname(protoName
);
2116 if (protoent
== NULL
)
2117 errx(1, "redirect_proto: unknown protocol %s", protoName
);
2119 proto
= protoent
->p_proto
;
2121 * Extract local address.
2123 ptr
= strtok(NULL
, " \t");
2125 errx(1, "redirect_proto: missing local address");
2127 StrToAddr(ptr
, &localAddr
);
2129 * Extract optional public address.
2131 ptr
= strtok(NULL
, " \t");
2133 StrToAddr(ptr
, &publicAddr
);
2135 publicAddr
.s_addr
= INADDR_ANY
;
2137 * Extract optional remote address.
2139 ptr
= strtok(NULL
, " \t");
2141 StrToAddr(ptr
, &remoteAddr
);
2143 remoteAddr
.s_addr
= INADDR_ANY
;
2145 * Create aliasing link.
2147 (void)PacketAliasRedirectProto(localAddr
, remoteAddr
, publicAddr
,
2151 void SetupAddressRedirect (const char* parms
)
2156 struct in_addr localAddr
;
2157 struct in_addr publicAddr
;
2159 struct alias_link
*link
;
2161 strcpy (buf
, parms
);
2163 * Extract local address.
2165 ptr
= strtok (buf
, " \t");
2167 errx (1, "redirect_address: missing local address");
2169 separator
= strchr(ptr
, ',');
2170 if (separator
) { /* LSNAT redirection syntax. */
2171 localAddr
.s_addr
= INADDR_NONE
;
2174 StrToAddr (ptr
, &localAddr
);
2178 * Extract public address.
2180 ptr
= strtok (NULL
, " \t");
2182 errx (1, "redirect_address: missing public address");
2184 StrToAddr (ptr
, &publicAddr
);
2185 link
= PacketAliasRedirectAddr(localAddr
, publicAddr
);
2188 * Setup LSNAT server pool.
2190 if (serverPool
!= NULL
&& link
!= NULL
) {
2191 ptr
= strtok(serverPool
, ",");
2192 while (ptr
!= NULL
) {
2193 StrToAddr(ptr
, &localAddr
);
2194 PacketAliasAddServer(link
, localAddr
, htons(~0));
2195 ptr
= strtok(NULL
, ",");
2200 void StrToAddr (const char* str
, struct in_addr
* addr
)
2204 if (inet_aton (str
, addr
))
2207 hp
= gethostbyname (str
);
2209 errx (1, "unknown host %s", str
);
2211 memcpy (addr
, hp
->h_addr
, sizeof (struct in_addr
));
2214 u_short
StrToPort (const char* str
, const char* proto
)
2220 port
= strtol (str
, &end
, 10);
2222 return htons (port
);
2224 sp
= getservbyname (str
, proto
);
2226 errx (1, "unknown service %s/%s", str
, proto
);
2231 int StrToPortRange (const char* str
, const char* proto
, port_range
*portRange
)
2239 /* First see if this is a service, return corresponding port if so. */
2240 sp
= getservbyname (str
,proto
);
2242 SETLOPORT(*portRange
, ntohs(sp
->s_port
));
2243 SETNUMPORTS(*portRange
, 1);
2247 /* Not a service, see if it's a single port or port range. */
2248 sep
= strchr (str
, '-');
2250 SETLOPORT(*portRange
, strtol(str
, &end
, 10));
2253 SETNUMPORTS(*portRange
, 1);
2257 /* Error in port range field. */
2258 errx (1, "unknown service %s/%s", str
, proto
);
2261 /* Port range, get the values and sanity check. */
2262 sscanf (str
, "%hu-%hu", &loPort
, &hiPort
);
2263 SETLOPORT(*portRange
, loPort
);
2264 SETNUMPORTS(*portRange
, 0); /* Error by default */
2265 if (loPort
<= hiPort
)
2266 SETNUMPORTS(*portRange
, hiPort
- loPort
+ 1);
2268 if (GETNUMPORTS(*portRange
) == 0)
2269 errx (1, "invalid port range %s", str
);
2275 int StrToProto (const char* str
)
2277 if (!strcmp (str
, "tcp"))
2280 if (!strcmp (str
, "udp"))
2283 errx (1, "unknown protocol %s. Expected tcp or udp", str
);
2286 int StrToAddrAndPortRange (const char* str
, struct in_addr
* addr
, char* proto
, port_range
*portRange
)
2290 ptr
= strchr (str
, ':');
2292 errx (1, "%s is missing port number", str
);
2297 StrToAddr (str
, addr
);
2298 return StrToPortRange (ptr
, proto
, portRange
);
2302 SetupPunchFW(const char *strValue
)
2304 unsigned int base
, num
;
2306 if (sscanf(strValue
, "%u:%u", &base
, &num
) != 2)
2307 errx(1, "punch_fw: basenumber:count parameter required");
2309 PacketAliasSetFWBase(base
, num
);
2310 (void)PacketAliasSetMode(PKT_ALIAS_PUNCH_FW
, PKT_ALIAS_PUNCH_FW
);