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 ParseOption (const char* option
, const char* parms
);
115 static void ReadConfigFile (const char* fileName
);
116 static void SetupPortRedirect (const char* parms
);
117 static void SetupProtoRedirect(const char* parms
);
118 static void SetupAddressRedirect (const char* parms
);
119 static void StrToAddr (const char* str
, struct in_addr
* addr
);
120 static u_short
StrToPort (const char* str
, const char* proto
);
121 static int StrToPortRange (const char* str
, const char* proto
, port_range
*portRange
);
122 static int StrToProto (const char* str
);
123 static int StrToAddrAndPortRange (const char* str
, struct in_addr
* addr
, char* proto
, port_range
*portRange
);
124 static void ParseArgs (int argc
, char** argv
);
125 static void FlushPacketBuffer (int fd
);
126 static void SetupPunchFW(const char *strValue
);
133 static int background
;
135 static int assignAliasAddr
;
138 static u_short inPort
;
139 static u_short outPort
;
140 static u_short inOutPort
;
141 static struct in_addr aliasAddr
;
142 static int dynamicMode
;
145 static int aliasOverhead
;
147 static char packetBuf
[IP_MAXPACKET
];
148 static int packetLen
;
149 static struct sockaddr_in packetAddr
;
150 static int packetSock
;
151 static int packetDirection
;
152 static int dropIgnoredIncoming
;
153 static int logDropped
;
154 static int logFacility
;
159 #define NATPMPORT 5351
161 #define NATPMVERSION 0
162 #define PUBLICADDRREQ 0
165 #define MAPUDPTCPREQ 3
166 #define SERVERREPLYOP 128
167 #define PUBLICADDRRLY SERVERREPLYOP+PUBLICADDRREQ
170 #define NOTSUPPORTEDVERSION 1
171 #define NOTAUTHORIZED 2
172 #define NETWORKFAILURE 3
173 #define OUTOFRESOURCES 4
174 #define UNSUPPORTEDOPCODE 5
176 #define TIMER_RATE 250
180 typedef struct stdportmaprequest
{
182 unsigned char opcode
;
183 unsigned short result
;
188 typedef struct publicaddrreply
{
190 unsigned char opcode
;
191 unsigned short result
;
195 typedef struct publicportreq
{
197 unsigned char opcode
;
198 unsigned short result
;
200 unsigned short privateport
;
201 unsigned short publicport
;
202 int lifetime
; /* in second */
204 typedef struct stderrreply
{
206 unsigned char opcode
;
207 unsigned short result
;
212 static int enable_natportmap
= 0;
213 static struct in_addr lastassignaliasAddr
;
214 static int portmapSock
= -1;
215 static struct in_addr
*forwardedinterfaceaddr
;
216 static char **forwardedinterfacename
;
217 static int numofinterfaces
= 0; /* has to be at least one */
218 static u_short natPMPport
;
219 static int numoftries
=MAXRETRY
;
220 static struct itimerval itval
;
221 static int Natdtimerset
= 0;
222 static double secdivisor
;
225 static void HandlePortMap( int fd
);
226 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
);
227 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
);
228 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*reply
, int publicport
);
229 static void Doubletime( struct timeval
*tvp
);
230 static void Stoptimer();
231 static void Natdtimer();
232 static void SendPortMapMulti( );
233 static void NotifyPublicAddress();
234 static void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
);
235 static void NatPortMapPInit();
236 static u_short
get_natportmap_port(void);
238 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
);
242 int main (int argc
, char** argv
)
248 struct sockaddr_in addr
;
253 * Initialize packet aliasing software.
254 * Done already here to be able to alter option bits
255 * during command line and configuration file processing.
270 aliasAddr
.s_addr
= INADDR_NONE
;
272 lastassignaliasAddr
.s_addr
= INADDR_NONE
;
277 logFacility
= LOG_DAEMON
;
279 * Mark packet buffer empty.
282 packetDirection
= DONT_KNOW
;
284 ParseArgs (argc
, argv
);
286 * Open syslog channel.
288 openlog ("natd", LOG_CONS
| LOG_PID
| (verbose
? LOG_PERROR
: 0),
291 * Check that valid aliasing address has been given.
293 if (aliasAddr
.s_addr
== INADDR_NONE
&& ifName
== NULL
)
294 errx (1, "aliasing address not given");
297 * Check that valid port number is known.
299 if (inPort
!= 0 || outPort
!= 0)
300 if (inPort
== 0 || outPort
== 0)
301 errx (1, "both input and output ports are required");
303 if (inPort
== 0 && outPort
== 0 && inOutPort
== 0)
304 ParseOption ("port", DEFAULT_SERVICE
);
307 * Check if ignored packets should be dropped.
309 dropIgnoredIncoming
= PacketAliasSetMode (0, 0);
310 dropIgnoredIncoming
&= PKT_ALIAS_DENY_INCOMING
;
312 * Create divert sockets. Use only one socket if -p was specified
313 * on command line. Otherwise, create separate sockets for
314 * outgoing and incoming connnections.
318 divertInOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
319 if (divertInOut
== -1)
320 Quit ("Unable to create divert socket.");
328 addr
.sin_family
= AF_INET
;
329 addr
.sin_addr
.s_addr
= INADDR_ANY
;
330 addr
.sin_port
= inOutPort
;
332 if (bind (divertInOut
,
333 (struct sockaddr
*) &addr
,
335 Quit ("Unable to bind divert socket.");
339 divertIn
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
341 Quit ("Unable to create incoming divert socket.");
343 divertOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
345 Quit ("Unable to create outgoing divert socket.");
350 * Bind divert sockets.
353 addr
.sin_family
= AF_INET
;
354 addr
.sin_addr
.s_addr
= INADDR_ANY
;
355 addr
.sin_port
= inPort
;
358 (struct sockaddr
*) &addr
,
360 Quit ("Unable to bind incoming divert socket.");
362 addr
.sin_family
= AF_INET
;
363 addr
.sin_addr
.s_addr
= INADDR_ANY
;
364 addr
.sin_port
= outPort
;
367 (struct sockaddr
*) &addr
,
369 Quit ("Unable to bind outgoing divert socket.");
372 * Create routing socket if interface name specified and in dynamic mode.
378 routeSock
= socket (PF_ROUTE
, SOCK_RAW
, 0);
380 Quit ("Unable to create routing info socket.");
385 SetAliasAddressFromIfName (ifName
);
389 * Create socket for sending ICMP messages.
391 icmpSock
= socket (AF_INET
, SOCK_RAW
, IPPROTO_ICMP
);
393 Quit ("Unable to create ICMP socket.");
396 * And disable reads for the socket, otherwise it slowly fills
397 * up with received icmps which we do not use.
399 shutdown(icmpSock
, SHUT_RD
);
403 if ( enable_natportmap
)
405 /* create socket to listen for port mapping */
406 portmapSock
= socket( AF_INET
, SOCK_DGRAM
, 0);
407 if ( portmapSock
!= -1 )
409 natPMPport
= get_natportmap_port();
410 addr
.sin_family
= AF_INET
;
411 addr
.sin_addr
.s_addr
= INADDR_ANY
;
412 addr
.sin_port
= NATPMPORT
;
414 if (bind ( portmapSock
,
415 (struct sockaddr
*) &addr
,
417 printf("Binding to NATPM port failed!\n");
419 /* NATPORTMAPP initial set up */
422 if ( !Natdtimerset
){
424 signal(SIGALRM
, Natdtimer
);
429 * Become a daemon unless verbose mode was requested.
434 * Catch signals to manage shutdown and
435 * refresh of interface address.
437 siginterrupt(SIGTERM
, 1);
438 siginterrupt(SIGHUP
, 1);
439 signal (SIGTERM
, InitiateShutdown
);
440 signal (SIGHUP
, RefreshAddr
);
442 * Set alias address if it has been given.
444 if (aliasAddr
.s_addr
!= INADDR_NONE
)
446 PacketAliasSetAddress (aliasAddr
);
448 if ( (enable_natportmap
) && (aliasAddr
.s_addr
!= lastassignaliasAddr
.s_addr
) ){
449 lastassignaliasAddr
.s_addr
= aliasAddr
.s_addr
;
450 NotifyPublicAddress();
455 * We need largest descriptor number for select.
460 if (divertIn
> fdMax
)
463 if (divertOut
> fdMax
)
466 if (divertInOut
> fdMax
)
469 if (routeSock
> fdMax
)
473 if ( portmapSock
> fdMax
)
480 if (divertInOut
!= -1 && !ifName
&& packetSock
== -1) {
482 * When using only one socket, just call
483 * DoAliasing repeatedly to process packets.
485 DoAliasing (divertInOut
, DONT_KNOW
);
489 * Build read mask from socket descriptors to select.
492 FD_ZERO (&writeMask
);
495 * If there is unsent packet in buffer, use select
496 * to check when socket comes writable again.
498 if (packetSock
!= -1) {
500 FD_SET (packetSock
, &writeMask
);
504 * No unsent packet exists - safe to check if
505 * new ones are available.
508 FD_SET (divertIn
, &readMask
);
511 FD_SET (divertOut
, &readMask
);
513 if (divertInOut
!= -1)
514 FD_SET (divertInOut
, &readMask
);
517 * Routing info is processed always.
520 FD_SET (routeSock
, &readMask
);
522 if ( portmapSock
!= -1 )
523 FD_SET (portmapSock
, &readMask
);
525 if (select (fdMax
+ 1,
534 Quit ("Select failed.");
537 if (packetSock
!= -1)
538 if (FD_ISSET (packetSock
, &writeMask
))
539 FlushPacketBuffer (packetSock
);
542 if (FD_ISSET (divertIn
, &readMask
))
543 DoAliasing (divertIn
, INPUT
);
546 if (FD_ISSET (divertOut
, &readMask
))
547 DoAliasing (divertOut
, OUTPUT
);
549 if (divertInOut
!= -1)
550 if (FD_ISSET (divertInOut
, &readMask
))
551 DoAliasing (divertInOut
, DONT_KNOW
);
554 if (FD_ISSET (routeSock
, &readMask
))
555 HandleRoutingInfo (routeSock
);
557 if ( portmapSock
!= -1)
558 if (FD_ISSET (portmapSock
, &readMask
))
559 HandlePortMap( portmapSock
);
569 static void DaemonMode ()
576 pidFile
= fopen (PIDFILE
, "w");
579 fprintf (pidFile
, "%d\n", getpid ());
584 static void ParseArgs (int argc
, char** argv
)
589 int len
; /* bounds checking */
591 for (arg
= 1; arg
< argc
; arg
++) {
596 warnx ("invalid option %s", opt
);
603 while (arg
< argc
- 1) {
605 if (argv
[arg
+ 1][0] == '-')
609 strncat (parmBuf
, " ", sizeof(parmBuf
) - (len
+ 1));
610 len
+= strlen(parmBuf
+ len
);
614 strncat (parmBuf
, argv
[arg
], sizeof(parmBuf
) - (len
+ 1));
615 len
+= strlen(parmBuf
+ len
);
619 ParseOption (opt
+ 1, (len
? parmBuf
: NULL
));
624 static void DoAliasing (int fd
, int direction
)
632 if (assignAliasAddr
) {
634 SetAliasAddressFromIfName (ifName
);
638 * Get packet from socket.
640 addrSize
= sizeof packetAddr
;
641 origBytes
= recvfrom (fd
,
645 (struct sockaddr
*) &packetAddr
,
648 if (origBytes
== -1) {
651 Warn ("read from divert socket failed");
656 * This is a IP packet.
658 ip
= (struct ip
*) packetBuf
;
659 if (direction
== DONT_KNOW
) {
660 if (packetAddr
.sin_addr
.s_addr
== INADDR_ANY
)
668 * Print packet direction and protocol type.
670 printf (direction
== OUTPUT
? "Out " : "In ");
686 printf ("[%d] ", ip
->ip_p
);
695 if (direction
== OUTPUT
) {
697 * Outgoing packets. Do aliasing.
699 PacketAliasOut (packetBuf
, IP_MAXPACKET
);
706 status
= PacketAliasIn (packetBuf
, IP_MAXPACKET
);
707 if (status
== PKT_ALIAS_IGNORED
&&
708 dropIgnoredIncoming
) {
711 printf (" dropped.\n");
714 SyslogPacket (ip
, LOG_WARNING
, "denied");
720 * Length might have changed during aliasing.
722 bytes
= ntohs (ip
->ip_len
);
724 * Update alias overhead size for outgoing packets.
726 if (direction
== OUTPUT
&&
727 bytes
- origBytes
> aliasOverhead
)
728 aliasOverhead
= bytes
- origBytes
;
733 * Print addresses after aliasing.
735 printf (" aliased to\n");
743 packetDirection
= direction
;
745 FlushPacketBuffer (fd
);
748 static void FlushPacketBuffer (int fd
)
753 * Put packet back for processing.
759 (struct sockaddr
*) &packetAddr
,
762 if (wrote
!= packetLen
) {
764 * If buffer space is not available,
765 * just return. Main loop will take care of
766 * retrying send when space becomes available.
768 if (errno
== ENOBUFS
)
771 if (errno
== EMSGSIZE
) {
773 if (packetDirection
== OUTPUT
&&
775 SendNeedFragIcmp (icmpSock
,
776 (struct ip
*) packetBuf
,
777 ifMTU
- aliasOverhead
);
781 sprintf (msgBuf
, "failed to write packet back");
789 static void HandleRoutingInfo (int fd
)
792 struct if_msghdr ifMsg
;
794 * Get packet from socket.
796 bytes
= read (fd
, &ifMsg
, sizeof ifMsg
);
799 Warn ("read from routing socket failed");
803 if (ifMsg
.ifm_version
!= RTM_VERSION
) {
805 Warn ("unexpected packet read from routing socket");
810 printf ("Routing message %#x received.\n", ifMsg
.ifm_type
);
812 if ((ifMsg
.ifm_type
== RTM_NEWADDR
|| ifMsg
.ifm_type
== RTM_IFINFO
) &&
813 ifMsg
.ifm_index
== ifIndex
) {
815 printf("Interface address/MTU has probably changed.\n");
824 struct mach_timebase_info info
;
826 (void) mach_timebase_info (&info
);
828 secdivisor
= ( (double)info
.denom
/ (double)info
.numer
) * 1000;
832 unsigned int getuptime()
835 unsigned long epochtime
;
837 now
= mach_absolute_time();
838 epochtime
= (now
/ secdivisor
) /USEC_PER_SEC
;
843 /* return NATPORTMAP port defined in /etc/servcies if there's one, else use NATPMPORT */
844 static u_short
get_natportmap_port(void)
848 ent
= getservbyname( "natportmap", "udp" );
850 return( ent
->s_port
);
855 /* set up neccessary info for doing NatPortMapP */
856 static void NatPortMapPInit()
859 struct ifaddrs
*ifap
, *ifa
;
861 forwardedinterfaceaddr
= (struct in_addr
*)
862 malloc(numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
863 bzero(forwardedinterfaceaddr
,
864 numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
865 /* interface address hasn't been set up, get interface address */
867 for ( ifa
= ifap
; ifa
; ifa
=ifa
->ifa_next
)
869 struct sockaddr_in
* a
;
870 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
874 a
= (struct sockaddr_in
*)ifa
->ifa_addr
;
875 for ( i
= 0; i
< numofinterfaces
; i
++ )
877 if (strcmp(ifa
->ifa_name
, forwardedinterfacename
[i
]))
881 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
883 /* copy the first IP address */
884 forwardedinterfaceaddr
[i
] = a
->sin_addr
;
893 /* SendPortMapResponse */
894 /* send generic reponses to NATPORTMAP requests */
895 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
)
900 reply
.version
= NATPMVERSION
;
901 reply
.opcode
= origopcode
+ SERVERREPLYOP
;
902 reply
.result
= result
;
903 reply
.epoch
= getuptime();
904 bytes
= sendto( fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
905 if ( bytes
!= sizeof(reply
) )
906 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
909 /* SendPublicAddress */
910 /* return public address to requestor */
911 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
)
914 publicaddrreply reply
;
917 reply
.version
= NATPMVERSION
;
918 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
919 reply
.result
= SUCCESS
;
920 reply
.addr
= lastassignaliasAddr
;
921 reply
.epoch
= getuptime();
923 bytes
= sendto (fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
924 if ( bytes
!= sizeof(reply
) )
925 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
928 /* SendPublicPortResponse */
929 /* response for portmap request and portmap removal request */
930 /* publicport <= 0 means error */
931 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*reply
, int publicport
)
936 reply
->version
= NATPMVERSION
;
937 reply
->opcode
= SERVERREPLYOP
+ reply
->opcode
;
938 if ( publicport
<= 0)
939 /* error in port mapping */
940 reply
->result
= OUTOFRESOURCES
;
942 reply
->result
= SUCCESS
;
943 reply
->epoch
= getuptime();
945 if ( reply
->lifetime
) /* not delete mapping */
946 reply
->publicport
= publicport
;
947 bytes
= sendto (fd
, (void*)reply
, sizeof(publicportreq
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
948 if ( bytes
!= sizeof(publicportreq
) )
949 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
->opcode
);
952 /* SendPortMapMulti */
953 /* send multicast to local network for new alias address */
954 static void SendPortMapMulti()
957 publicaddrreply reply
;
959 struct sockaddr_in multiaddr
;
963 #define LOCALGROUP "224.0.0.1"
965 memset(&multiaddr
,0,sizeof(struct sockaddr_in
));
966 multiaddr
.sin_family
=AF_INET
;
967 multiaddr
.sin_addr
.s_addr
=inet_addr(LOCALGROUP
);
968 multiaddr
.sin_port
=htons(NATPMPORT
);
969 reply
.version
= NATPMVERSION
;
970 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
971 reply
.result
= SUCCESS
;
972 reply
.addr
= lastassignaliasAddr
;
975 /* send multicast to all forwarded interfaces */
976 for ( i
= 0; i
< numofinterfaces
; i
++)
978 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
982 multisock
= socket( AF_INET
, SOCK_DGRAM
, 0);
984 if ( multisock
== -1 )
986 printf("cannot get socket for sending multicast\n");
989 if (setsockopt(multisock
, IPPROTO_IP
, IP_MULTICAST_IF
, &forwardedinterfaceaddr
[i
], sizeof(struct in_addr
)) < 0)
991 printf("setsockopt failed\n");
995 bytes
= sendto (multisock
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)&multiaddr
, sizeof(multiaddr
));
996 if ( bytes
!= sizeof(reply
) )
997 printf( "PORTMAP::problem sending multicast alias address - opcode %d\n", reply
.opcode
);
1003 /* double the time value */
1004 static void Doubletime( struct timeval
*tvp
)
1011 if (tvp
->tv_usec
>= 1000000) {
1012 tvp
->tv_sec
+= tvp
->tv_usec
/ 1000000;
1013 tvp
->tv_usec
= tvp
->tv_usec
% 1000000;
1017 /* stop running natd timer */
1018 static void Stoptimer()
1020 itval
.it_value
.tv_usec
= 0;
1021 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1022 printf( "setitimer err: %d\n", errno
);
1026 /* timer routine to send new public IP address */
1027 static void Natdtimer()
1029 if ( !enable_natportmap
)
1034 if ( numoftries
< MAXRETRY
){
1035 Doubletime( &itval
.it_value
);
1036 itval
.it_interval
= itval
.it_value
;
1037 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1038 printf( "setitimer err: %d\n", errno
);
1048 /* NotifyPublicAddress */
1049 /* Advertise new public address */
1050 static void NotifyPublicAddress()
1052 if ( numoftries
< MAXRETRY
)
1054 /* there is an old timer running, cancel it */
1057 /* send up new timer */
1060 itval
.it_value
.tv_sec
= 0;
1061 itval
.it_value
.tv_usec
= TIMER_RATE
;
1062 itval
.it_interval
.tv_sec
= 0;
1063 itval
.it_interval
.tv_usec
= TIMER_RATE
;
1064 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1065 printf( "setitimer err: %d\n", errno
);
1070 /* find/add/remove port mapping from alias manager */
1071 void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
)
1073 u_char proto
= IPPROTO_TCP
;
1076 if ( req
->opcode
== MAPUDPREQ
)
1077 proto
= IPPROTO_UDP
;
1078 if ( req
->lifetime
== 0)
1080 /* remove port mapping */
1081 if ( !FindAliasPortOut( clientaddr
->sin_addr
, lastassignaliasAddr
, req
->privateport
, req
->publicport
, proto
, req
->lifetime
, 0))
1082 /* FindAliasPortOut returns no error, port successfully removed, return no error response to client */
1083 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, 1 );
1085 /* deleting port fails, return error */
1086 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, -1 );
1090 /* look for port mapping - public port is ignored in this case */
1091 /* create port mapping - map provided public port to private port if public port is not 0 */
1092 aliasport
= FindAliasPortOut( clientaddr
->sin_addr
, lastassignaliasAddr
, req
->privateport
, req
->publicport
, proto
, req
->lifetime
, 1);
1093 /* aliasport should be non zero if mapping is successfully, else -1 is returned, alias port shouldn't be zero???? */
1094 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, aliasport
);
1100 /* handle all packets sent to NATPORTMAP port */
1101 static void HandlePortMap( int fd
)
1103 #define MAXBUFFERSIZE 100
1105 struct sockaddr_in clientaddr
;
1107 unsigned char buffer
[MAXBUFFERSIZE
];
1109 unsigned short result
= SUCCESS
;
1110 struct stdportmaprequest
*req
;
1112 clientaddrlen
= sizeof( clientaddr
);
1113 bytes
= recvfrom( fd
, buffer
, sizeof(buffer
), 0, (struct sockaddr
*)&clientaddr
, &clientaddrlen
);
1116 printf( "Read NATPM port error\n");
1119 req
= (struct stdportmaprequest
*)buffer
;
1125 for ( i
= 0; i
<bytes
; i
++)
1127 printf("%d", buffer
[i
]);
1132 /* check client version */
1133 if ( req
->version
> NATPMVERSION
)
1134 result
= NOTSUPPORTEDVERSION
;
1135 else if ( !enable_natportmap
)
1136 /* natd wasn't launched with portmapping enabled */
1137 result
= NOTAUTHORIZED
;
1141 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, result
);
1145 switch ( req
->opcode
)
1149 SendPublicAddress(fd
, &clientaddr
, clientaddrlen
);
1157 DoPortMapping( fd
, &clientaddr
, clientaddrlen
, (publicportreq
*)req
);
1163 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, UNSUPPORTEDOPCODE
);
1171 static void PrintPacket (struct ip
* ip
)
1173 printf ("%s", FormatPacket (ip
));
1176 static void SyslogPacket (struct ip
* ip
, int priority
, const char *label
)
1178 syslog (priority
, "%s %s", label
, FormatPacket (ip
));
1181 static char* FormatPacket (struct ip
* ip
)
1183 static char buf
[256];
1184 struct tcphdr
* tcphdr
;
1185 struct udphdr
* udphdr
;
1186 struct icmp
* icmphdr
;
1190 strcpy (src
, inet_ntoa (ip
->ip_src
));
1191 strcpy (dst
, inet_ntoa (ip
->ip_dst
));
1195 tcphdr
= (struct tcphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1196 sprintf (buf
, "[TCP] %s:%d -> %s:%d",
1198 ntohs (tcphdr
->th_sport
),
1200 ntohs (tcphdr
->th_dport
));
1204 udphdr
= (struct udphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1205 sprintf (buf
, "[UDP] %s:%d -> %s:%d",
1207 ntohs (udphdr
->uh_sport
),
1209 ntohs (udphdr
->uh_dport
));
1213 icmphdr
= (struct icmp
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1214 sprintf (buf
, "[ICMP] %s -> %s %u(%u)",
1218 icmphdr
->icmp_code
);
1222 sprintf (buf
, "[%d] %s -> %s ", ip
->ip_p
, src
, dst
);
1230 SetAliasAddressFromIfName(const char *ifn
)
1234 char *buf
, *lim
, *next
;
1235 struct if_msghdr
*ifm
;
1236 struct ifa_msghdr
*ifam
;
1237 struct sockaddr_dl
*sdl
;
1238 struct sockaddr_in
*sin
;
1243 mib
[3] = AF_INET
; /* Only IP addresses please */
1244 mib
[4] = NET_RT_IFLIST
;
1245 mib
[5] = 0; /* ifIndex??? */
1247 * Get interface data.
1249 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1)
1250 err(1, "iflist-sysctl-estimate");
1251 if ((buf
= malloc(needed
)) == NULL
)
1252 errx(1, "malloc failed");
1253 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1)
1254 err(1, "iflist-sysctl-get");
1257 * Loop through interfaces until one with
1258 * given name is found. This is done to
1259 * find correct interface index for routing
1260 * message processing.
1264 while (next
< lim
) {
1265 ifm
= (struct if_msghdr
*)next
;
1266 next
+= ifm
->ifm_msglen
;
1267 if (ifm
->ifm_version
!= RTM_VERSION
) {
1269 warnx("routing message version %d "
1270 "not understood", ifm
->ifm_version
);
1273 if (ifm
->ifm_type
== RTM_IFINFO
) {
1274 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
1275 if (strlen(ifn
) == sdl
->sdl_nlen
&&
1276 strncmp(ifn
, sdl
->sdl_data
, sdl
->sdl_nlen
) == 0) {
1277 ifIndex
= ifm
->ifm_index
;
1278 ifMTU
= ifm
->ifm_data
.ifi_mtu
;
1280 PacketAliasClampMSS(ifMTU
- sizeof(struct tcphdr
) - sizeof(struct ip
));
1286 errx(1, "unknown interface name %s", ifn
);
1288 * Get interface address.
1290 if (aliasAddr
.s_addr
== INADDR_NONE
) {
1292 while (next
< lim
) {
1293 ifam
= (struct ifa_msghdr
*)next
;
1294 next
+= ifam
->ifam_msglen
;
1295 if (ifam
->ifam_version
!= RTM_VERSION
) {
1297 warnx("routing message version %d "
1298 "not understood", ifam
->ifam_version
);
1301 if (ifam
->ifam_type
!= RTM_NEWADDR
)
1303 if (ifam
->ifam_addrs
& RTA_IFA
) {
1305 char *cp
= (char *)(ifam
+ 1);
1307 #define ROUNDUP(a) \
1308 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1309 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
1311 for (i
= 1; i
< RTA_IFA
; i
<<= 1)
1312 if (ifam
->ifam_addrs
& i
)
1313 ADVANCE(cp
, (struct sockaddr
*)cp
);
1314 if (((struct sockaddr
*)cp
)->sa_family
== AF_INET
) {
1315 sin
= (struct sockaddr_in
*)cp
;
1321 errx(1, "%s: cannot get interface address", ifn
);
1323 PacketAliasSetAddress(sin
->sin_addr
);
1325 if ( (enable_natportmap
) && (sin
->sin_addr
.s_addr
!= lastassignaliasAddr
.s_addr
) )
1327 lastassignaliasAddr
.s_addr
= sin
->sin_addr
.s_addr
;
1328 /* make sure the timer handler was set before setting timer */
1329 if ( !Natdtimerset
){
1331 signal(SIGALRM
, Natdtimer
);
1333 NotifyPublicAddress();
1336 syslog(LOG_INFO
, "Aliasing to %s, mtu %d bytes",
1337 inet_ntoa(sin
->sin_addr
), ifMTU
);
1343 void Quit (const char* msg
)
1349 void Warn (const char* msg
)
1352 syslog (LOG_ALERT
, "%s (%m)", msg
);
1357 static void RefreshAddr (int sig
)
1360 assignAliasAddr
= 1;
1363 static void InitiateShutdown (int sig
)
1366 * Start timer to allow kernel gracefully
1367 * shutdown existing connections when system
1370 siginterrupt(SIGALRM
, 1);
1371 signal (SIGALRM
, Shutdown
);
1375 static void Shutdown (int sig
)
1381 * Different options recognized by this program.
1421 * Option information structure (used by ParseOption).
1429 const char* parmDescription
;
1430 const char* description
;
1432 const char* shortName
;
1436 * Table of known options.
1439 static struct OptionInfo optionTable
[] = {
1441 { PacketAliasOption
,
1442 PKT_ALIAS_UNREGISTERED_ONLY
,
1445 "alias only unregistered addresses",
1446 "unregistered_only",
1449 { PacketAliasOption
,
1457 { PacketAliasOption
,
1458 PKT_ALIAS_PROXY_ONLY
,
1465 { PacketAliasOption
,
1469 "operate in reverse mode",
1473 { PacketAliasOption
,
1474 PKT_ALIAS_DENY_INCOMING
,
1477 "allow incoming connections",
1481 { PacketAliasOption
,
1482 PKT_ALIAS_USE_SOCKETS
,
1485 "use sockets to inhibit port conflict",
1489 { PacketAliasOption
,
1490 PKT_ALIAS_SAME_PORTS
,
1493 "try to keep original port numbers for connections",
1501 "verbose mode, dump packet information",
1509 "dynamic mode, automatically detect interface address changes",
1517 "enable TCP MSS clamping",
1524 "number|service_name",
1525 "set port for incoming packets",
1532 "number|service_name",
1533 "set port for outgoing packets",
1540 "number|service_name",
1541 "set port (defaults to natd/divert)",
1549 "address to use for aliasing",
1557 "address to use for incoming sessions",
1565 "take aliasing address from interface",
1572 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1574 "add transparent proxying / destination NAT",
1581 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range"
1582 " [remote_addr[:remote_port_range]]",
1583 "redirect a port (or ports) for incoming traffic",
1590 "proto local_addr [public_addr] [remote_addr]",
1591 "redirect packets of a given proto",
1598 "local_addr[,...] public_addr",
1599 "define mapping between local and public addresses",
1607 "read options from configuration file",
1615 "enable logging of denied incoming packets",
1623 "name of syslog facility to use for logging",
1631 "punch holes in the firewall for incoming FTP/IRC DCC connections",
1640 "enable NATPortMap protocol",
1641 "enable_natportmap",
1648 "take aliasing address to interface",
1649 "natportmap_interface",
1655 static void ParseOption (const char* option
, const char* parms
)
1658 struct OptionInfo
* info
;
1663 const char* strValue
;
1664 struct in_addr addrValue
;
1667 CODE
* fac_record
= NULL
;
1669 * Find option from table.
1671 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1672 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1674 if (!strcmp (info
->name
, option
))
1677 if (info
->shortName
)
1678 if (!strcmp (info
->shortName
, option
))
1684 warnx ("unknown option %s", option
);
1695 switch (info
->parm
) {
1700 if (!strcmp (parms
, "yes"))
1703 if (!strcmp (parms
, "no"))
1706 errx (1, "%s needs yes/no parameter", option
);
1711 errx (1, "%s needs service name or "
1712 "port number parameter",
1715 uNumValue
= StrToPort (parms
, "divert");
1720 numValue
= strtol (parms
, &end
, 10);
1725 errx (1, "%s needs numeric parameter", option
);
1731 errx (1, "%s needs parameter", option
);
1736 errx (1, "%s does not take parameters", option
);
1741 errx (1, "%s needs address/host parameter", option
);
1743 StrToAddr (parms
, &addrValue
);
1747 switch (info
->type
) {
1748 case PacketAliasOption
:
1750 aliasValue
= yesNoValue
? info
->packetAliasOpt
: 0;
1751 PacketAliasSetMode (aliasValue
, info
->packetAliasOpt
);
1755 verbose
= yesNoValue
;
1759 dynamicMode
= yesNoValue
;
1763 clampMSS
= yesNoValue
;
1771 outPort
= uNumValue
;
1775 inOutPort
= uNumValue
;
1779 memcpy (&aliasAddr
, &addrValue
, sizeof (struct in_addr
));
1783 PacketAliasSetTarget(addrValue
);
1787 SetupPortRedirect (strValue
);
1791 SetupProtoRedirect(strValue
);
1794 case RedirectAddress
:
1795 SetupAddressRedirect (strValue
);
1799 PacketAliasProxyRule (strValue
);
1806 ifName
= strdup (strValue
);
1810 ReadConfigFile (strValue
);
1819 fac_record
= facilitynames
;
1820 while (fac_record
->c_name
!= NULL
) {
1822 if (!strcmp (fac_record
->c_name
, strValue
)) {
1824 logFacility
= fac_record
->c_val
;
1832 if(fac_record
->c_name
== NULL
)
1833 errx(1, "Unknown log facility name: %s", strValue
);
1838 SetupPunchFW(strValue
);
1843 enable_natportmap
= yesNoValue
;
1847 case ToInterfaceName
:
1849 if (forwardedinterfacename
!= NULL
)
1851 if ( realloc(forwardedinterfacename
, (numofinterfaces
+1) * sizeof(*forwardedinterfacename
)) == NULL
){
1852 printf("realloc error, cannot allocate memory for fowarded interface name.\n");
1857 if ( (forwardedinterfacename
= malloc( sizeof(*forwardedinterfacename
) )) == NULL
){
1858 printf("malloc error, cannot allocate memory for fowarded interface name.\n");
1863 forwardedinterfacename
[numofinterfaces
] = strdup(strValue
);
1874 void ReadConfigFile (const char* fileName
)
1882 file
= fopen (fileName
, "r");
1884 err(1, "cannot open config file %s", fileName
);
1886 while ((buf
= fgetln(file
, &len
)) != NULL
) {
1887 if (buf
[len
- 1] == '\n')
1888 buf
[len
- 1] = '\0';
1890 errx(1, "config file format error: "
1891 "last line should end with newline");
1894 * Check for comments, strip off trailing spaces.
1896 if ((ptr
= strchr(buf
, '#')))
1898 for (ptr
= buf
; isspace(*ptr
); ++ptr
)
1902 for (p
= strchr(buf
, '\0'); isspace(*--p
);)
1907 * Extract option name.
1910 while (*ptr
&& !isspace (*ptr
))
1919 * Skip white space between name and parms.
1921 while (*ptr
&& isspace (*ptr
))
1924 ParseOption (option
, *ptr
? ptr
: NULL
);
1930 static void Usage ()
1934 struct OptionInfo
* info
;
1936 fprintf (stderr
, "Recognized options:\n\n");
1938 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1939 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1941 fprintf (stderr
, "-%-20s %s\n", info
->name
,
1942 info
->parmDescription
);
1944 if (info
->shortName
)
1945 fprintf (stderr
, "-%-20s %s\n", info
->shortName
,
1946 info
->parmDescription
);
1948 fprintf (stderr
, " %s\n\n", info
->description
);
1954 void SetupPortRedirect (const char* parms
)
1959 struct in_addr localAddr
;
1960 struct in_addr publicAddr
;
1961 struct in_addr remoteAddr
;
1962 port_range portRange
;
1963 u_short localPort
= 0;
1964 u_short publicPort
= 0;
1965 u_short remotePort
= 0;
1966 u_short numLocalPorts
= 0;
1967 u_short numPublicPorts
= 0;
1968 u_short numRemotePorts
= 0;
1973 struct alias_link
*link
= NULL
;
1975 strcpy (buf
, parms
);
1979 protoName
= strtok (buf
, " \t");
1981 errx (1, "redirect_port: missing protocol");
1983 proto
= StrToProto (protoName
);
1985 * Extract local address.
1987 ptr
= strtok (NULL
, " \t");
1989 errx (1, "redirect_port: missing local address");
1991 separator
= strchr(ptr
, ',');
1992 if (separator
) { /* LSNAT redirection syntax. */
1993 localAddr
.s_addr
= INADDR_NONE
;
1998 if ( StrToAddrAndPortRange (ptr
, &localAddr
, protoName
, &portRange
) != 0 )
1999 errx (1, "redirect_port: invalid local port range");
2001 localPort
= GETLOPORT(portRange
);
2002 numLocalPorts
= GETNUMPORTS(portRange
);
2007 * Extract public port and optionally address.
2009 ptr
= strtok (NULL
, " \t");
2011 errx (1, "redirect_port: missing public port");
2013 separator
= strchr (ptr
, ':');
2015 if (StrToAddrAndPortRange (ptr
, &publicAddr
, protoName
, &portRange
) != 0 )
2016 errx (1, "redirect_port: invalid public port range");
2019 publicAddr
.s_addr
= INADDR_ANY
;
2020 if (StrToPortRange (ptr
, protoName
, &portRange
) != 0)
2021 errx (1, "redirect_port: invalid public port range");
2024 publicPort
= GETLOPORT(portRange
);
2025 numPublicPorts
= GETNUMPORTS(portRange
);
2028 * Extract remote address and optionally port.
2030 ptr
= strtok (NULL
, " \t");
2032 separator
= strchr (ptr
, ':');
2034 if (StrToAddrAndPortRange (ptr
, &remoteAddr
, protoName
, &portRange
) != 0)
2035 errx (1, "redirect_port: invalid remote port range");
2037 SETLOPORT(portRange
, 0);
2038 SETNUMPORTS(portRange
, 1);
2039 StrToAddr (ptr
, &remoteAddr
);
2043 SETLOPORT(portRange
, 0);
2044 SETNUMPORTS(portRange
, 1);
2045 remoteAddr
.s_addr
= INADDR_ANY
;
2048 remotePort
= GETLOPORT(portRange
);
2049 numRemotePorts
= GETNUMPORTS(portRange
);
2052 * Make sure port ranges match up, then add the redirect ports.
2054 if (numLocalPorts
!= numPublicPorts
)
2055 errx (1, "redirect_port: port ranges must be equal in size");
2057 /* Remote port range is allowed to be '0' which means all ports. */
2058 if (numRemotePorts
!= numLocalPorts
&& (numRemotePorts
!= 1 || remotePort
!= 0))
2059 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
2061 for (i
= 0 ; i
< numPublicPorts
; ++i
) {
2062 /* If remotePort is all ports, set it to 0. */
2063 u_short remotePortCopy
= remotePort
+ i
;
2064 if (numRemotePorts
== 1 && remotePort
== 0)
2067 link
= PacketAliasRedirectPort (localAddr
,
2068 htons(localPort
+ i
),
2070 htons(remotePortCopy
),
2072 htons(publicPort
+ i
),
2077 * Setup LSNAT server pool.
2079 if (serverPool
!= NULL
&& link
!= NULL
) {
2080 ptr
= strtok(serverPool
, ",");
2081 while (ptr
!= NULL
) {
2082 if (StrToAddrAndPortRange(ptr
, &localAddr
, protoName
, &portRange
) != 0)
2083 errx(1, "redirect_port: invalid local port range");
2085 localPort
= GETLOPORT(portRange
);
2086 if (GETNUMPORTS(portRange
) != 1)
2087 errx(1, "redirect_port: local port must be single in this context");
2088 PacketAliasAddServer(link
, localAddr
, htons(localPort
));
2089 ptr
= strtok(NULL
, ",");
2095 SetupProtoRedirect(const char* parms
)
2099 struct in_addr localAddr
;
2100 struct in_addr publicAddr
;
2101 struct in_addr remoteAddr
;
2104 struct protoent
*protoent
;
2106 strcpy (buf
, parms
);
2110 protoName
= strtok(buf
, " \t");
2112 errx(1, "redirect_proto: missing protocol");
2114 protoent
= getprotobyname(protoName
);
2115 if (protoent
== NULL
)
2116 errx(1, "redirect_proto: unknown protocol %s", protoName
);
2118 proto
= protoent
->p_proto
;
2120 * Extract local address.
2122 ptr
= strtok(NULL
, " \t");
2124 errx(1, "redirect_proto: missing local address");
2126 StrToAddr(ptr
, &localAddr
);
2128 * Extract optional public address.
2130 ptr
= strtok(NULL
, " \t");
2132 StrToAddr(ptr
, &publicAddr
);
2134 publicAddr
.s_addr
= INADDR_ANY
;
2136 * Extract optional remote address.
2138 ptr
= strtok(NULL
, " \t");
2140 StrToAddr(ptr
, &remoteAddr
);
2142 remoteAddr
.s_addr
= INADDR_ANY
;
2144 * Create aliasing link.
2146 (void)PacketAliasRedirectProto(localAddr
, remoteAddr
, publicAddr
,
2150 void SetupAddressRedirect (const char* parms
)
2155 struct in_addr localAddr
;
2156 struct in_addr publicAddr
;
2158 struct alias_link
*link
;
2160 strcpy (buf
, parms
);
2162 * Extract local address.
2164 ptr
= strtok (buf
, " \t");
2166 errx (1, "redirect_address: missing local address");
2168 separator
= strchr(ptr
, ',');
2169 if (separator
) { /* LSNAT redirection syntax. */
2170 localAddr
.s_addr
= INADDR_NONE
;
2173 StrToAddr (ptr
, &localAddr
);
2177 * Extract public address.
2179 ptr
= strtok (NULL
, " \t");
2181 errx (1, "redirect_address: missing public address");
2183 StrToAddr (ptr
, &publicAddr
);
2184 link
= PacketAliasRedirectAddr(localAddr
, publicAddr
);
2187 * Setup LSNAT server pool.
2189 if (serverPool
!= NULL
&& link
!= NULL
) {
2190 ptr
= strtok(serverPool
, ",");
2191 while (ptr
!= NULL
) {
2192 StrToAddr(ptr
, &localAddr
);
2193 PacketAliasAddServer(link
, localAddr
, htons(~0));
2194 ptr
= strtok(NULL
, ",");
2199 void StrToAddr (const char* str
, struct in_addr
* addr
)
2203 if (inet_aton (str
, addr
))
2206 hp
= gethostbyname (str
);
2208 errx (1, "unknown host %s", str
);
2210 memcpy (addr
, hp
->h_addr
, sizeof (struct in_addr
));
2213 u_short
StrToPort (const char* str
, const char* proto
)
2219 port
= strtol (str
, &end
, 10);
2221 return htons (port
);
2223 sp
= getservbyname (str
, proto
);
2225 errx (1, "unknown service %s/%s", str
, proto
);
2230 int StrToPortRange (const char* str
, const char* proto
, port_range
*portRange
)
2238 /* First see if this is a service, return corresponding port if so. */
2239 sp
= getservbyname (str
,proto
);
2241 SETLOPORT(*portRange
, ntohs(sp
->s_port
));
2242 SETNUMPORTS(*portRange
, 1);
2246 /* Not a service, see if it's a single port or port range. */
2247 sep
= strchr (str
, '-');
2249 SETLOPORT(*portRange
, strtol(str
, &end
, 10));
2252 SETNUMPORTS(*portRange
, 1);
2256 /* Error in port range field. */
2257 errx (1, "unknown service %s/%s", str
, proto
);
2260 /* Port range, get the values and sanity check. */
2261 sscanf (str
, "%hu-%hu", &loPort
, &hiPort
);
2262 SETLOPORT(*portRange
, loPort
);
2263 SETNUMPORTS(*portRange
, 0); /* Error by default */
2264 if (loPort
<= hiPort
)
2265 SETNUMPORTS(*portRange
, hiPort
- loPort
+ 1);
2267 if (GETNUMPORTS(*portRange
) == 0)
2268 errx (1, "invalid port range %s", str
);
2274 int StrToProto (const char* str
)
2276 if (!strcmp (str
, "tcp"))
2279 if (!strcmp (str
, "udp"))
2282 errx (1, "unknown protocol %s. Expected tcp or udp", str
);
2285 int StrToAddrAndPortRange (const char* str
, struct in_addr
* addr
, char* proto
, port_range
*portRange
)
2289 ptr
= strchr (str
, ':');
2291 errx (1, "%s is missing port number", str
);
2296 StrToAddr (str
, addr
);
2297 return StrToPortRange (ptr
, proto
, portRange
);
2301 SetupPunchFW(const char *strValue
)
2303 unsigned int base
, num
;
2305 if (sscanf(strValue
, "%u:%u", &base
, &num
) != 2)
2306 errx(1, "punch_fw: basenumber:count parameter required");
2308 PacketAliasSetFWBase(base
, num
);
2309 (void)PacketAliasSetMode(PKT_ALIAS_PUNCH_FW
, PKT_ALIAS_PUNCH_FW
);