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
;
187 typedef struct publicaddrreply
{
189 unsigned char opcode
;
190 unsigned short result
;
194 typedef struct publicportreq
{
196 unsigned char opcode
;
197 unsigned short result
;
198 unsigned short privateport
;
199 unsigned short publicport
;
200 int lifetime
; /* in second */
202 typedef struct publicportreply
{
204 unsigned char opcode
;
205 unsigned short result
;
207 unsigned short privateport
;
208 unsigned short publicport
;
209 int lifetime
; /* in second */
211 typedef struct stderrreply
{
213 unsigned char opcode
;
214 unsigned short result
;
219 static int enable_natportmap
= 0;
220 static struct in_addr lastassignaliasAddr
;
221 static int portmapSock
= -1;
222 static struct in_addr
*forwardedinterfaceaddr
;
223 static char **forwardedinterfacename
;
224 static int numofinterfaces
= 0; /* has to be at least one */
225 static u_short natPMPport
;
226 static int numoftries
=MAXRETRY
;
227 static struct itimerval itval
;
228 static int Natdtimerset
= 0;
229 static double secdivisor
;
232 static void HandlePortMap( int fd
);
233 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
);
234 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
);
235 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*reply
, int publicport
);
236 static void Doubletime( struct timeval
*tvp
);
237 static void Stoptimer();
238 static void Natdtimer();
239 static void SendPortMapMulti( );
240 static void NotifyPublicAddress();
241 static void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
);
242 static void NatPortMapPInit();
243 static u_short
get_natportmap_port(void);
245 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
);
249 int main (int argc
, char** argv
)
255 struct sockaddr_in addr
;
260 * Initialize packet aliasing software.
261 * Done already here to be able to alter option bits
262 * during command line and configuration file processing.
277 aliasAddr
.s_addr
= INADDR_NONE
;
279 lastassignaliasAddr
.s_addr
= INADDR_NONE
;
284 logFacility
= LOG_DAEMON
;
286 * Mark packet buffer empty.
289 packetDirection
= DONT_KNOW
;
291 ParseArgs (argc
, argv
);
293 * Open syslog channel.
295 openlog ("natd", LOG_CONS
| LOG_PID
| (verbose
? LOG_PERROR
: 0),
298 * Check that valid aliasing address has been given.
300 if (aliasAddr
.s_addr
== INADDR_NONE
&& ifName
== NULL
)
301 errx (1, "aliasing address not given");
304 * Check that valid port number is known.
306 if (inPort
!= 0 || outPort
!= 0)
307 if (inPort
== 0 || outPort
== 0)
308 errx (1, "both input and output ports are required");
310 if (inPort
== 0 && outPort
== 0 && inOutPort
== 0)
311 ParseOption ("port", DEFAULT_SERVICE
);
314 * Check if ignored packets should be dropped.
316 dropIgnoredIncoming
= PacketAliasSetMode (0, 0);
317 dropIgnoredIncoming
&= PKT_ALIAS_DENY_INCOMING
;
319 * Create divert sockets. Use only one socket if -p was specified
320 * on command line. Otherwise, create separate sockets for
321 * outgoing and incoming connnections.
325 divertInOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
326 if (divertInOut
== -1)
327 Quit ("Unable to create divert socket.");
335 addr
.sin_family
= AF_INET
;
336 addr
.sin_addr
.s_addr
= INADDR_ANY
;
337 addr
.sin_port
= inOutPort
;
339 if (bind (divertInOut
,
340 (struct sockaddr
*) &addr
,
342 Quit ("Unable to bind divert socket.");
346 divertIn
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
348 Quit ("Unable to create incoming divert socket.");
350 divertOut
= socket (PF_INET
, SOCK_RAW
, IPPROTO_DIVERT
);
352 Quit ("Unable to create outgoing divert socket.");
357 * Bind divert sockets.
360 addr
.sin_family
= AF_INET
;
361 addr
.sin_addr
.s_addr
= INADDR_ANY
;
362 addr
.sin_port
= inPort
;
365 (struct sockaddr
*) &addr
,
367 Quit ("Unable to bind incoming divert socket.");
369 addr
.sin_family
= AF_INET
;
370 addr
.sin_addr
.s_addr
= INADDR_ANY
;
371 addr
.sin_port
= outPort
;
374 (struct sockaddr
*) &addr
,
376 Quit ("Unable to bind outgoing divert socket.");
379 * Create routing socket if interface name specified and in dynamic mode.
385 routeSock
= socket (PF_ROUTE
, SOCK_RAW
, 0);
387 Quit ("Unable to create routing info socket.");
392 SetAliasAddressFromIfName (ifName
);
396 * Create socket for sending ICMP messages.
398 icmpSock
= socket (AF_INET
, SOCK_RAW
, IPPROTO_ICMP
);
400 Quit ("Unable to create ICMP socket.");
403 * And disable reads for the socket, otherwise it slowly fills
404 * up with received icmps which we do not use.
406 shutdown(icmpSock
, SHUT_RD
);
410 if ( enable_natportmap
)
412 /* create socket to listen for port mapping */
413 portmapSock
= socket( AF_INET
, SOCK_DGRAM
, 0);
414 if ( portmapSock
!= -1 )
416 natPMPport
= htons(get_natportmap_port());
417 addr
.sin_family
= AF_INET
;
418 addr
.sin_addr
.s_addr
= INADDR_ANY
;
419 addr
.sin_port
= htons(NATPMPORT
);
421 if (bind ( portmapSock
,
422 (struct sockaddr
*) &addr
,
424 printf("Binding to NATPM port failed!\n");
426 /* NATPORTMAPP initial set up */
429 if ( !Natdtimerset
){
431 signal(SIGALRM
, Natdtimer
);
436 * Become a daemon unless verbose mode was requested.
441 * Catch signals to manage shutdown and
442 * refresh of interface address.
444 siginterrupt(SIGTERM
, 1);
445 siginterrupt(SIGHUP
, 1);
446 signal (SIGTERM
, InitiateShutdown
);
447 signal (SIGHUP
, RefreshAddr
);
449 * Set alias address if it has been given.
451 if (aliasAddr
.s_addr
!= INADDR_NONE
)
453 PacketAliasSetAddress (aliasAddr
);
455 if ( (enable_natportmap
) && (aliasAddr
.s_addr
!= lastassignaliasAddr
.s_addr
) ){
456 lastassignaliasAddr
.s_addr
= aliasAddr
.s_addr
;
457 NotifyPublicAddress();
462 * We need largest descriptor number for select.
467 if (divertIn
> fdMax
)
470 if (divertOut
> fdMax
)
473 if (divertInOut
> fdMax
)
476 if (routeSock
> fdMax
)
480 if ( portmapSock
> fdMax
)
487 if (divertInOut
!= -1 && !ifName
&& packetSock
== -1) {
489 * When using only one socket, just call
490 * DoAliasing repeatedly to process packets.
492 DoAliasing (divertInOut
, DONT_KNOW
);
496 * Build read mask from socket descriptors to select.
499 FD_ZERO (&writeMask
);
502 * If there is unsent packet in buffer, use select
503 * to check when socket comes writable again.
505 if (packetSock
!= -1) {
507 FD_SET (packetSock
, &writeMask
);
511 * No unsent packet exists - safe to check if
512 * new ones are available.
515 FD_SET (divertIn
, &readMask
);
518 FD_SET (divertOut
, &readMask
);
520 if (divertInOut
!= -1)
521 FD_SET (divertInOut
, &readMask
);
524 * Routing info is processed always.
527 FD_SET (routeSock
, &readMask
);
529 if ( portmapSock
!= -1 )
530 FD_SET (portmapSock
, &readMask
);
532 if (select (fdMax
+ 1,
541 Quit ("Select failed.");
544 if (packetSock
!= -1)
545 if (FD_ISSET (packetSock
, &writeMask
))
546 FlushPacketBuffer (packetSock
);
549 if (FD_ISSET (divertIn
, &readMask
))
550 DoAliasing (divertIn
, INPUT
);
553 if (FD_ISSET (divertOut
, &readMask
))
554 DoAliasing (divertOut
, OUTPUT
);
556 if (divertInOut
!= -1)
557 if (FD_ISSET (divertInOut
, &readMask
))
558 DoAliasing (divertInOut
, DONT_KNOW
);
561 if (FD_ISSET (routeSock
, &readMask
))
562 HandleRoutingInfo (routeSock
);
564 if ( portmapSock
!= -1)
565 if (FD_ISSET (portmapSock
, &readMask
))
566 HandlePortMap( portmapSock
);
576 static void DaemonMode ()
583 pidFile
= fopen (PIDFILE
, "w");
586 fprintf (pidFile
, "%d\n", getpid ());
591 static void ParseArgs (int argc
, char** argv
)
596 int len
; /* bounds checking */
598 for (arg
= 1; arg
< argc
; arg
++) {
603 warnx ("invalid option %s", opt
);
610 while (arg
< argc
- 1) {
612 if (argv
[arg
+ 1][0] == '-')
616 strncat (parmBuf
, " ", sizeof(parmBuf
) - (len
+ 1));
617 len
+= strlen(parmBuf
+ len
);
621 strncat (parmBuf
, argv
[arg
], sizeof(parmBuf
) - (len
+ 1));
622 len
+= strlen(parmBuf
+ len
);
626 ParseOption (opt
+ 1, (len
? parmBuf
: NULL
));
631 static void DoAliasing (int fd
, int direction
)
639 if (assignAliasAddr
) {
641 SetAliasAddressFromIfName (ifName
);
645 * Get packet from socket.
647 addrSize
= sizeof packetAddr
;
648 origBytes
= recvfrom (fd
,
652 (struct sockaddr
*) &packetAddr
,
655 if (origBytes
== -1) {
658 Warn ("read from divert socket failed");
663 * This is a IP packet.
665 ip
= (struct ip
*) packetBuf
;
666 if (direction
== DONT_KNOW
) {
667 if (packetAddr
.sin_addr
.s_addr
== INADDR_ANY
)
675 * Print packet direction and protocol type.
677 printf (direction
== OUTPUT
? "Out " : "In ");
693 printf ("[%d] ", ip
->ip_p
);
702 if (direction
== OUTPUT
) {
704 * Outgoing packets. Do aliasing.
706 PacketAliasOut (packetBuf
, IP_MAXPACKET
);
713 status
= PacketAliasIn (packetBuf
, IP_MAXPACKET
);
714 if (status
== PKT_ALIAS_IGNORED
&&
715 dropIgnoredIncoming
) {
718 printf (" dropped.\n");
721 SyslogPacket (ip
, LOG_WARNING
, "denied");
727 * Length might have changed during aliasing.
729 bytes
= ntohs (ip
->ip_len
);
731 * Update alias overhead size for outgoing packets.
733 if (direction
== OUTPUT
&&
734 bytes
- origBytes
> aliasOverhead
)
735 aliasOverhead
= bytes
- origBytes
;
740 * Print addresses after aliasing.
742 printf (" aliased to\n");
750 packetDirection
= direction
;
752 FlushPacketBuffer (fd
);
755 static void FlushPacketBuffer (int fd
)
760 * Put packet back for processing.
766 (struct sockaddr
*) &packetAddr
,
769 if (wrote
!= packetLen
) {
771 * If buffer space is not available,
772 * just return. Main loop will take care of
773 * retrying send when space becomes available.
775 if (errno
== ENOBUFS
)
778 if (errno
== EMSGSIZE
) {
780 if (packetDirection
== OUTPUT
&&
782 SendNeedFragIcmp (icmpSock
,
783 (struct ip
*) packetBuf
,
784 ifMTU
- aliasOverhead
);
788 sprintf (msgBuf
, "failed to write packet back");
796 static void HandleRoutingInfo (int fd
)
799 struct if_msghdr ifMsg
;
801 * Get packet from socket.
803 bytes
= read (fd
, &ifMsg
, sizeof ifMsg
);
806 Warn ("read from routing socket failed");
810 if (ifMsg
.ifm_version
!= RTM_VERSION
) {
812 Warn ("unexpected packet read from routing socket");
817 printf ("Routing message %#x received.\n", ifMsg
.ifm_type
);
819 if ((ifMsg
.ifm_type
== RTM_NEWADDR
|| ifMsg
.ifm_type
== RTM_IFINFO
) &&
820 ifMsg
.ifm_index
== ifIndex
) {
822 printf("Interface address/MTU has probably changed.\n");
831 struct mach_timebase_info info
;
833 (void) mach_timebase_info (&info
);
835 secdivisor
= ( (double)info
.denom
/ (double)info
.numer
) * 1000;
839 unsigned int getuptime()
842 unsigned long epochtime
;
844 now
= mach_absolute_time();
845 epochtime
= (now
/ secdivisor
) /USEC_PER_SEC
;
850 /* return NATPORTMAP port defined in /etc/servcies if there's one, else use NATPMPORT */
851 static u_short
get_natportmap_port(void)
855 ent
= getservbyname( "natportmap", "udp" );
857 return( ent
->s_port
);
862 /* set up neccessary info for doing NatPortMapP */
863 static void NatPortMapPInit()
866 struct ifaddrs
*ifap
, *ifa
;
868 forwardedinterfaceaddr
= (struct in_addr
*)
869 malloc(numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
870 bzero(forwardedinterfaceaddr
,
871 numofinterfaces
* sizeof(*forwardedinterfaceaddr
));
872 /* interface address hasn't been set up, get interface address */
874 for ( ifa
= ifap
; ifa
; ifa
=ifa
->ifa_next
)
876 struct sockaddr_in
* a
;
877 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
881 a
= (struct sockaddr_in
*)ifa
->ifa_addr
;
882 for ( i
= 0; i
< numofinterfaces
; i
++ )
884 if (strcmp(ifa
->ifa_name
, forwardedinterfacename
[i
]))
888 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
890 /* copy the first IP address */
891 forwardedinterfaceaddr
[i
] = a
->sin_addr
;
900 /* SendPortMapResponse */
901 /* send generic reponses to NATPORTMAP requests */
902 static void SendPortMapResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, unsigned char origopcode
, unsigned short result
)
907 reply
.version
= NATPMVERSION
;
908 reply
.opcode
= origopcode
+ SERVERREPLYOP
;
909 reply
.result
= result
;
910 reply
.epoch
= getuptime();
911 bytes
= sendto( fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
912 if ( bytes
!= sizeof(reply
) )
913 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
916 /* SendPublicAddress */
917 /* return public address to requestor */
918 static void SendPublicAddress( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
)
921 publicaddrreply reply
;
924 reply
.version
= NATPMVERSION
;
925 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
926 reply
.result
= SUCCESS
;
927 reply
.addr
= lastassignaliasAddr
;
928 reply
.epoch
= getuptime();
930 bytes
= sendto (fd
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
931 if ( bytes
!= sizeof(reply
) )
932 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply
.opcode
);
935 /* SendPublicPortResponse */
936 /* response for portmap request and portmap removal request */
937 /* publicport <= 0 means error */
938 static void SendPublicPortResponse( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
, int publicport
)
942 publicportreply reply
;
944 reply
.version
= NATPMVERSION
;
945 reply
.opcode
= SERVERREPLYOP
+ req
->opcode
;
946 if ( publicport
<= 0)
947 /* error in port mapping */
948 reply
.result
= OUTOFRESOURCES
;
950 reply
.result
= SUCCESS
;
951 reply
.epoch
= getuptime();
953 if ( req
->lifetime
){ /* not delete mapping */
954 reply
.privateport
= req
->privateport
;
955 reply
.publicport
= publicport
;
957 bytes
= sendto (fd
, (void*)&reply
, sizeof(publicportreply
), 0, (struct sockaddr
*)clientaddr
, clientaddrlen
);
958 if ( bytes
!= sizeof(publicportreply
) )
959 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", req
->opcode
);
962 /* SendPortMapMulti */
963 /* send multicast to local network for new alias address */
964 static void SendPortMapMulti()
967 publicaddrreply reply
;
969 struct sockaddr_in multiaddr
;
973 #define LOCALGROUP "224.0.0.1"
975 memset(&multiaddr
,0,sizeof(struct sockaddr_in
));
976 multiaddr
.sin_family
=AF_INET
;
977 multiaddr
.sin_addr
.s_addr
=inet_addr(LOCALGROUP
);
978 multiaddr
.sin_port
=htons(NATPMPORT
);
979 reply
.version
= NATPMVERSION
;
980 reply
.opcode
= SERVERREPLYOP
+ PUBLICADDRREQ
;
981 reply
.result
= SUCCESS
;
982 reply
.addr
= lastassignaliasAddr
;
985 /* send multicast to all forwarded interfaces */
986 for ( i
= 0; i
< numofinterfaces
; i
++)
988 if (forwardedinterfaceaddr
[i
].s_addr
== 0)
992 multisock
= socket( AF_INET
, SOCK_DGRAM
, 0);
994 if ( multisock
== -1 )
996 printf("cannot get socket for sending multicast\n");
999 if (setsockopt(multisock
, IPPROTO_IP
, IP_MULTICAST_IF
, &forwardedinterfaceaddr
[i
], sizeof(struct in_addr
)) < 0)
1001 printf("setsockopt failed\n");
1005 bytes
= sendto (multisock
, (void*)&reply
, sizeof(reply
), 0, (struct sockaddr
*)&multiaddr
, sizeof(multiaddr
));
1006 if ( bytes
!= sizeof(reply
) )
1007 printf( "PORTMAP::problem sending multicast alias address - opcode %d\n", reply
.opcode
);
1013 /* double the time value */
1014 static void Doubletime( struct timeval
*tvp
)
1021 if (tvp
->tv_usec
>= 1000000) {
1022 tvp
->tv_sec
+= tvp
->tv_usec
/ 1000000;
1023 tvp
->tv_usec
= tvp
->tv_usec
% 1000000;
1027 /* stop running natd timer */
1028 static void Stoptimer()
1030 itval
.it_value
.tv_usec
= 0;
1031 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1032 printf( "setitimer err: %d\n", errno
);
1036 /* timer routine to send new public IP address */
1037 static void Natdtimer()
1039 if ( !enable_natportmap
)
1044 if ( numoftries
< MAXRETRY
){
1045 Doubletime( &itval
.it_value
);
1046 itval
.it_interval
= itval
.it_value
;
1047 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1048 printf( "setitimer err: %d\n", errno
);
1058 /* NotifyPublicAddress */
1059 /* Advertise new public address */
1060 static void NotifyPublicAddress()
1062 if ( numoftries
< MAXRETRY
)
1064 /* there is an old timer running, cancel it */
1067 /* send up new timer */
1070 itval
.it_value
.tv_sec
= 0;
1071 itval
.it_value
.tv_usec
= TIMER_RATE
;
1072 itval
.it_interval
.tv_sec
= 0;
1073 itval
.it_interval
.tv_usec
= TIMER_RATE
;
1074 if (setitimer(ITIMER_REAL
, &itval
, (struct itimerval
*)NULL
) < 0)
1075 printf( "setitimer err: %d\n", errno
);
1080 /* find/add/remove port mapping from alias manager */
1081 void DoPortMapping( int fd
, struct sockaddr_in
*clientaddr
, int clientaddrlen
, publicportreq
*req
)
1083 u_char proto
= IPPROTO_TCP
;
1086 if ( req
->opcode
== MAPUDPREQ
)
1087 proto
= IPPROTO_UDP
;
1088 if ( req
->lifetime
== 0)
1090 /* remove port mapping */
1091 if ( !FindAliasPortOut( clientaddr
->sin_addr
, lastassignaliasAddr
, req
->privateport
, req
->publicport
, proto
, req
->lifetime
, 0))
1092 /* FindAliasPortOut returns no error, port successfully removed, return no error response to client */
1093 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, 1 );
1095 /* deleting port fails, return error */
1096 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, -1 );
1100 /* look for port mapping - public port is ignored in this case */
1101 /* create port mapping - map provided public port to private port if public port is not 0 */
1102 aliasport
= FindAliasPortOut( clientaddr
->sin_addr
, lastassignaliasAddr
, req
->privateport
, req
->publicport
, proto
, req
->lifetime
, 1);
1103 /* aliasport should be non zero if mapping is successfully, else -1 is returned, alias port shouldn't be zero???? */
1104 SendPublicPortResponse( fd
, clientaddr
, clientaddrlen
, req
, aliasport
);
1110 /* handle all packets sent to NATPORTMAP port */
1111 static void HandlePortMap( int fd
)
1113 #define MAXBUFFERSIZE 100
1115 struct sockaddr_in clientaddr
;
1117 unsigned char buffer
[MAXBUFFERSIZE
];
1119 unsigned short result
= SUCCESS
;
1120 struct stdportmaprequest
*req
;
1122 clientaddrlen
= sizeof( clientaddr
);
1123 bytes
= recvfrom( fd
, buffer
, sizeof(buffer
), 0, (struct sockaddr
*)&clientaddr
, &clientaddrlen
);
1126 printf( "Read NATPM port error\n");
1129 req
= (struct stdportmaprequest
*)buffer
;
1135 for ( i
= 0; i
<bytes
; i
++)
1137 printf("%d", buffer
[i
]);
1142 /* check client version */
1143 if ( req
->version
> NATPMVERSION
)
1144 result
= NOTSUPPORTEDVERSION
;
1145 else if ( !enable_natportmap
)
1146 /* natd wasn't launched with portmapping enabled */
1147 result
= NOTAUTHORIZED
;
1151 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, result
);
1155 switch ( req
->opcode
)
1159 SendPublicAddress(fd
, &clientaddr
, clientaddrlen
);
1167 DoPortMapping( fd
, &clientaddr
, clientaddrlen
, (publicportreq
*)req
);
1173 SendPortMapResponse( fd
, &clientaddr
, clientaddrlen
, req
->opcode
, UNSUPPORTEDOPCODE
);
1181 static void PrintPacket (struct ip
* ip
)
1183 printf ("%s", FormatPacket (ip
));
1186 static void SyslogPacket (struct ip
* ip
, int priority
, const char *label
)
1188 syslog (priority
, "%s %s", label
, FormatPacket (ip
));
1191 static char* FormatPacket (struct ip
* ip
)
1193 static char buf
[256];
1194 struct tcphdr
* tcphdr
;
1195 struct udphdr
* udphdr
;
1196 struct icmp
* icmphdr
;
1200 strcpy (src
, inet_ntoa (ip
->ip_src
));
1201 strcpy (dst
, inet_ntoa (ip
->ip_dst
));
1205 tcphdr
= (struct tcphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1206 sprintf (buf
, "[TCP] %s:%d -> %s:%d",
1208 ntohs (tcphdr
->th_sport
),
1210 ntohs (tcphdr
->th_dport
));
1214 udphdr
= (struct udphdr
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1215 sprintf (buf
, "[UDP] %s:%d -> %s:%d",
1217 ntohs (udphdr
->uh_sport
),
1219 ntohs (udphdr
->uh_dport
));
1223 icmphdr
= (struct icmp
*) ((char*) ip
+ (ip
->ip_hl
<< 2));
1224 sprintf (buf
, "[ICMP] %s -> %s %u(%u)",
1228 icmphdr
->icmp_code
);
1232 sprintf (buf
, "[%d] %s -> %s ", ip
->ip_p
, src
, dst
);
1240 SetAliasAddressFromIfName(const char *ifn
)
1244 char *buf
, *lim
, *next
;
1245 struct if_msghdr
*ifm
;
1246 struct ifa_msghdr
*ifam
;
1247 struct sockaddr_dl
*sdl
;
1248 struct sockaddr_in
*sin
;
1253 mib
[3] = AF_INET
; /* Only IP addresses please */
1254 mib
[4] = NET_RT_IFLIST
;
1255 mib
[5] = 0; /* ifIndex??? */
1257 * Get interface data.
1259 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1)
1260 err(1, "iflist-sysctl-estimate");
1261 if ((buf
= malloc(needed
)) == NULL
)
1262 errx(1, "malloc failed");
1263 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) == -1)
1264 err(1, "iflist-sysctl-get");
1267 * Loop through interfaces until one with
1268 * given name is found. This is done to
1269 * find correct interface index for routing
1270 * message processing.
1274 while (next
< lim
) {
1275 ifm
= (struct if_msghdr
*)next
;
1276 next
+= ifm
->ifm_msglen
;
1277 if (ifm
->ifm_version
!= RTM_VERSION
) {
1279 warnx("routing message version %d "
1280 "not understood", ifm
->ifm_version
);
1283 if (ifm
->ifm_type
== RTM_IFINFO
) {
1284 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
1285 if (strlen(ifn
) == sdl
->sdl_nlen
&&
1286 strncmp(ifn
, sdl
->sdl_data
, sdl
->sdl_nlen
) == 0) {
1287 ifIndex
= ifm
->ifm_index
;
1288 ifMTU
= ifm
->ifm_data
.ifi_mtu
;
1290 PacketAliasClampMSS(ifMTU
- sizeof(struct tcphdr
) - sizeof(struct ip
));
1296 errx(1, "unknown interface name %s", ifn
);
1298 * Get interface address.
1300 if (aliasAddr
.s_addr
== INADDR_NONE
) {
1302 while (next
< lim
) {
1303 ifam
= (struct ifa_msghdr
*)next
;
1304 next
+= ifam
->ifam_msglen
;
1305 if (ifam
->ifam_version
!= RTM_VERSION
) {
1307 warnx("routing message version %d "
1308 "not understood", ifam
->ifam_version
);
1311 if (ifam
->ifam_type
!= RTM_NEWADDR
)
1313 if (ifam
->ifam_addrs
& RTA_IFA
) {
1315 char *cp
= (char *)(ifam
+ 1);
1317 #define ROUNDUP(a) \
1318 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1319 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
1321 for (i
= 1; i
< RTA_IFA
; i
<<= 1)
1322 if (ifam
->ifam_addrs
& i
)
1323 ADVANCE(cp
, (struct sockaddr
*)cp
);
1324 if (((struct sockaddr
*)cp
)->sa_family
== AF_INET
) {
1325 sin
= (struct sockaddr_in
*)cp
;
1331 errx(1, "%s: cannot get interface address", ifn
);
1333 PacketAliasSetAddress(sin
->sin_addr
);
1335 if ( (enable_natportmap
) && (sin
->sin_addr
.s_addr
!= lastassignaliasAddr
.s_addr
) )
1337 lastassignaliasAddr
.s_addr
= sin
->sin_addr
.s_addr
;
1338 /* make sure the timer handler was set before setting timer */
1339 if ( !Natdtimerset
){
1341 signal(SIGALRM
, Natdtimer
);
1343 NotifyPublicAddress();
1346 syslog(LOG_INFO
, "Aliasing to %s, mtu %d bytes",
1347 inet_ntoa(sin
->sin_addr
), ifMTU
);
1353 void Quit (const char* msg
)
1359 void Warn (const char* msg
)
1362 syslog (LOG_ALERT
, "%s (%m)", msg
);
1367 static void RefreshAddr (int sig
)
1370 assignAliasAddr
= 1;
1373 static void InitiateShutdown (int sig
)
1376 * Start timer to allow kernel gracefully
1377 * shutdown existing connections when system
1380 siginterrupt(SIGALRM
, 1);
1381 signal (SIGALRM
, Shutdown
);
1385 static void Shutdown (int sig
)
1391 * Different options recognized by this program.
1431 * Option information structure (used by ParseOption).
1439 const char* parmDescription
;
1440 const char* description
;
1442 const char* shortName
;
1446 * Table of known options.
1449 static struct OptionInfo optionTable
[] = {
1451 { PacketAliasOption
,
1452 PKT_ALIAS_UNREGISTERED_ONLY
,
1455 "alias only unregistered addresses",
1456 "unregistered_only",
1459 { PacketAliasOption
,
1467 { PacketAliasOption
,
1468 PKT_ALIAS_PROXY_ONLY
,
1475 { PacketAliasOption
,
1479 "operate in reverse mode",
1483 { PacketAliasOption
,
1484 PKT_ALIAS_DENY_INCOMING
,
1487 "allow incoming connections",
1491 { PacketAliasOption
,
1492 PKT_ALIAS_USE_SOCKETS
,
1495 "use sockets to inhibit port conflict",
1499 { PacketAliasOption
,
1500 PKT_ALIAS_SAME_PORTS
,
1503 "try to keep original port numbers for connections",
1511 "verbose mode, dump packet information",
1519 "dynamic mode, automatically detect interface address changes",
1527 "enable TCP MSS clamping",
1534 "number|service_name",
1535 "set port for incoming packets",
1542 "number|service_name",
1543 "set port for outgoing packets",
1550 "number|service_name",
1551 "set port (defaults to natd/divert)",
1559 "address to use for aliasing",
1567 "address to use for incoming sessions",
1575 "take aliasing address from interface",
1582 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1584 "add transparent proxying / destination NAT",
1591 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range"
1592 " [remote_addr[:remote_port_range]]",
1593 "redirect a port (or ports) for incoming traffic",
1600 "proto local_addr [public_addr] [remote_addr]",
1601 "redirect packets of a given proto",
1608 "local_addr[,...] public_addr",
1609 "define mapping between local and public addresses",
1617 "read options from configuration file",
1625 "enable logging of denied incoming packets",
1633 "name of syslog facility to use for logging",
1641 "punch holes in the firewall for incoming FTP/IRC DCC connections",
1650 "enable NATPortMap protocol",
1651 "enable_natportmap",
1658 "take aliasing address to interface",
1659 "natportmap_interface",
1665 static void ParseOption (const char* option
, const char* parms
)
1668 struct OptionInfo
* info
;
1673 const char* strValue
;
1674 struct in_addr addrValue
;
1677 CODE
* fac_record
= NULL
;
1679 * Find option from table.
1681 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1682 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1684 if (!strcmp (info
->name
, option
))
1687 if (info
->shortName
)
1688 if (!strcmp (info
->shortName
, option
))
1694 warnx ("unknown option %s", option
);
1705 switch (info
->parm
) {
1710 if (!strcmp (parms
, "yes"))
1713 if (!strcmp (parms
, "no"))
1716 errx (1, "%s needs yes/no parameter", option
);
1721 errx (1, "%s needs service name or "
1722 "port number parameter",
1725 uNumValue
= StrToPort (parms
, "divert");
1730 numValue
= strtol (parms
, &end
, 10);
1735 errx (1, "%s needs numeric parameter", option
);
1741 errx (1, "%s needs parameter", option
);
1746 errx (1, "%s does not take parameters", option
);
1751 errx (1, "%s needs address/host parameter", option
);
1753 StrToAddr (parms
, &addrValue
);
1757 switch (info
->type
) {
1758 case PacketAliasOption
:
1760 aliasValue
= yesNoValue
? info
->packetAliasOpt
: 0;
1761 PacketAliasSetMode (aliasValue
, info
->packetAliasOpt
);
1765 verbose
= yesNoValue
;
1769 dynamicMode
= yesNoValue
;
1773 clampMSS
= yesNoValue
;
1781 outPort
= uNumValue
;
1785 inOutPort
= uNumValue
;
1789 memcpy (&aliasAddr
, &addrValue
, sizeof (struct in_addr
));
1793 PacketAliasSetTarget(addrValue
);
1797 SetupPortRedirect (strValue
);
1801 SetupProtoRedirect(strValue
);
1804 case RedirectAddress
:
1805 SetupAddressRedirect (strValue
);
1809 PacketAliasProxyRule (strValue
);
1816 ifName
= strdup (strValue
);
1820 ReadConfigFile (strValue
);
1829 fac_record
= facilitynames
;
1830 while (fac_record
->c_name
!= NULL
) {
1832 if (!strcmp (fac_record
->c_name
, strValue
)) {
1834 logFacility
= fac_record
->c_val
;
1842 if(fac_record
->c_name
== NULL
)
1843 errx(1, "Unknown log facility name: %s", strValue
);
1848 SetupPunchFW(strValue
);
1853 enable_natportmap
= yesNoValue
;
1857 case ToInterfaceName
:
1859 if (forwardedinterfacename
!= NULL
)
1861 if ( realloc(forwardedinterfacename
, (numofinterfaces
+1) * sizeof(*forwardedinterfacename
)) == NULL
){
1862 printf("realloc error, cannot allocate memory for fowarded interface name.\n");
1867 if ( (forwardedinterfacename
= malloc( sizeof(*forwardedinterfacename
) )) == NULL
){
1868 printf("malloc error, cannot allocate memory for fowarded interface name.\n");
1873 forwardedinterfacename
[numofinterfaces
] = strdup(strValue
);
1884 void ReadConfigFile (const char* fileName
)
1892 file
= fopen (fileName
, "r");
1894 err(1, "cannot open config file %s", fileName
);
1896 while ((buf
= fgetln(file
, &len
)) != NULL
) {
1897 if (buf
[len
- 1] == '\n')
1898 buf
[len
- 1] = '\0';
1900 errx(1, "config file format error: "
1901 "last line should end with newline");
1904 * Check for comments, strip off trailing spaces.
1906 if ((ptr
= strchr(buf
, '#')))
1908 for (ptr
= buf
; isspace(*ptr
); ++ptr
)
1912 for (p
= strchr(buf
, '\0'); isspace(*--p
);)
1917 * Extract option name.
1920 while (*ptr
&& !isspace (*ptr
))
1929 * Skip white space between name and parms.
1931 while (*ptr
&& isspace (*ptr
))
1934 ParseOption (option
, *ptr
? ptr
: NULL
);
1940 static void Usage ()
1944 struct OptionInfo
* info
;
1946 fprintf (stderr
, "Recognized options:\n\n");
1948 max
= sizeof (optionTable
) / sizeof (struct OptionInfo
);
1949 for (i
= 0, info
= optionTable
; i
< max
; i
++, info
++) {
1951 fprintf (stderr
, "-%-20s %s\n", info
->name
,
1952 info
->parmDescription
);
1954 if (info
->shortName
)
1955 fprintf (stderr
, "-%-20s %s\n", info
->shortName
,
1956 info
->parmDescription
);
1958 fprintf (stderr
, " %s\n\n", info
->description
);
1964 void SetupPortRedirect (const char* parms
)
1969 struct in_addr localAddr
;
1970 struct in_addr publicAddr
;
1971 struct in_addr remoteAddr
;
1972 port_range portRange
;
1973 u_short localPort
= 0;
1974 u_short publicPort
= 0;
1975 u_short remotePort
= 0;
1976 u_short numLocalPorts
= 0;
1977 u_short numPublicPorts
= 0;
1978 u_short numRemotePorts
= 0;
1983 struct alias_link
*link
= NULL
;
1985 strcpy (buf
, parms
);
1989 protoName
= strtok (buf
, " \t");
1991 errx (1, "redirect_port: missing protocol");
1993 proto
= StrToProto (protoName
);
1995 * Extract local address.
1997 ptr
= strtok (NULL
, " \t");
1999 errx (1, "redirect_port: missing local address");
2001 separator
= strchr(ptr
, ',');
2002 if (separator
) { /* LSNAT redirection syntax. */
2003 localAddr
.s_addr
= INADDR_NONE
;
2008 if ( StrToAddrAndPortRange (ptr
, &localAddr
, protoName
, &portRange
) != 0 )
2009 errx (1, "redirect_port: invalid local port range");
2011 localPort
= GETLOPORT(portRange
);
2012 numLocalPorts
= GETNUMPORTS(portRange
);
2017 * Extract public port and optionally address.
2019 ptr
= strtok (NULL
, " \t");
2021 errx (1, "redirect_port: missing public port");
2023 separator
= strchr (ptr
, ':');
2025 if (StrToAddrAndPortRange (ptr
, &publicAddr
, protoName
, &portRange
) != 0 )
2026 errx (1, "redirect_port: invalid public port range");
2029 publicAddr
.s_addr
= INADDR_ANY
;
2030 if (StrToPortRange (ptr
, protoName
, &portRange
) != 0)
2031 errx (1, "redirect_port: invalid public port range");
2034 publicPort
= GETLOPORT(portRange
);
2035 numPublicPorts
= GETNUMPORTS(portRange
);
2038 * Extract remote address and optionally port.
2040 ptr
= strtok (NULL
, " \t");
2042 separator
= strchr (ptr
, ':');
2044 if (StrToAddrAndPortRange (ptr
, &remoteAddr
, protoName
, &portRange
) != 0)
2045 errx (1, "redirect_port: invalid remote port range");
2047 SETLOPORT(portRange
, 0);
2048 SETNUMPORTS(portRange
, 1);
2049 StrToAddr (ptr
, &remoteAddr
);
2053 SETLOPORT(portRange
, 0);
2054 SETNUMPORTS(portRange
, 1);
2055 remoteAddr
.s_addr
= INADDR_ANY
;
2058 remotePort
= GETLOPORT(portRange
);
2059 numRemotePorts
= GETNUMPORTS(portRange
);
2062 * Make sure port ranges match up, then add the redirect ports.
2064 if (numLocalPorts
!= numPublicPorts
)
2065 errx (1, "redirect_port: port ranges must be equal in size");
2067 /* Remote port range is allowed to be '0' which means all ports. */
2068 if (numRemotePorts
!= numLocalPorts
&& (numRemotePorts
!= 1 || remotePort
!= 0))
2069 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
2071 for (i
= 0 ; i
< numPublicPorts
; ++i
) {
2072 /* If remotePort is all ports, set it to 0. */
2073 u_short remotePortCopy
= remotePort
+ i
;
2074 if (numRemotePorts
== 1 && remotePort
== 0)
2077 link
= PacketAliasRedirectPort (localAddr
,
2078 htons(localPort
+ i
),
2080 htons(remotePortCopy
),
2082 htons(publicPort
+ i
),
2087 * Setup LSNAT server pool.
2089 if (serverPool
!= NULL
&& link
!= NULL
) {
2090 ptr
= strtok(serverPool
, ",");
2091 while (ptr
!= NULL
) {
2092 if (StrToAddrAndPortRange(ptr
, &localAddr
, protoName
, &portRange
) != 0)
2093 errx(1, "redirect_port: invalid local port range");
2095 localPort
= GETLOPORT(portRange
);
2096 if (GETNUMPORTS(portRange
) != 1)
2097 errx(1, "redirect_port: local port must be single in this context");
2098 PacketAliasAddServer(link
, localAddr
, htons(localPort
));
2099 ptr
= strtok(NULL
, ",");
2105 SetupProtoRedirect(const char* parms
)
2109 struct in_addr localAddr
;
2110 struct in_addr publicAddr
;
2111 struct in_addr remoteAddr
;
2114 struct protoent
*protoent
;
2116 strcpy (buf
, parms
);
2120 protoName
= strtok(buf
, " \t");
2122 errx(1, "redirect_proto: missing protocol");
2124 protoent
= getprotobyname(protoName
);
2125 if (protoent
== NULL
)
2126 errx(1, "redirect_proto: unknown protocol %s", protoName
);
2128 proto
= protoent
->p_proto
;
2130 * Extract local address.
2132 ptr
= strtok(NULL
, " \t");
2134 errx(1, "redirect_proto: missing local address");
2136 StrToAddr(ptr
, &localAddr
);
2138 * Extract optional public address.
2140 ptr
= strtok(NULL
, " \t");
2142 StrToAddr(ptr
, &publicAddr
);
2144 publicAddr
.s_addr
= INADDR_ANY
;
2146 * Extract optional remote address.
2148 ptr
= strtok(NULL
, " \t");
2150 StrToAddr(ptr
, &remoteAddr
);
2152 remoteAddr
.s_addr
= INADDR_ANY
;
2154 * Create aliasing link.
2156 (void)PacketAliasRedirectProto(localAddr
, remoteAddr
, publicAddr
,
2160 void SetupAddressRedirect (const char* parms
)
2165 struct in_addr localAddr
;
2166 struct in_addr publicAddr
;
2168 struct alias_link
*link
;
2170 strcpy (buf
, parms
);
2172 * Extract local address.
2174 ptr
= strtok (buf
, " \t");
2176 errx (1, "redirect_address: missing local address");
2178 separator
= strchr(ptr
, ',');
2179 if (separator
) { /* LSNAT redirection syntax. */
2180 localAddr
.s_addr
= INADDR_NONE
;
2183 StrToAddr (ptr
, &localAddr
);
2187 * Extract public address.
2189 ptr
= strtok (NULL
, " \t");
2191 errx (1, "redirect_address: missing public address");
2193 StrToAddr (ptr
, &publicAddr
);
2194 link
= PacketAliasRedirectAddr(localAddr
, publicAddr
);
2197 * Setup LSNAT server pool.
2199 if (serverPool
!= NULL
&& link
!= NULL
) {
2200 ptr
= strtok(serverPool
, ",");
2201 while (ptr
!= NULL
) {
2202 StrToAddr(ptr
, &localAddr
);
2203 PacketAliasAddServer(link
, localAddr
, htons(~0));
2204 ptr
= strtok(NULL
, ",");
2209 void StrToAddr (const char* str
, struct in_addr
* addr
)
2213 if (inet_aton (str
, addr
))
2216 hp
= gethostbyname (str
);
2218 errx (1, "unknown host %s", str
);
2220 memcpy (addr
, hp
->h_addr
, sizeof (struct in_addr
));
2223 u_short
StrToPort (const char* str
, const char* proto
)
2229 port
= strtol (str
, &end
, 10);
2231 return htons (port
);
2233 sp
= getservbyname (str
, proto
);
2235 errx (1, "unknown service %s/%s", str
, proto
);
2240 int StrToPortRange (const char* str
, const char* proto
, port_range
*portRange
)
2248 /* First see if this is a service, return corresponding port if so. */
2249 sp
= getservbyname (str
,proto
);
2251 SETLOPORT(*portRange
, ntohs(sp
->s_port
));
2252 SETNUMPORTS(*portRange
, 1);
2256 /* Not a service, see if it's a single port or port range. */
2257 sep
= strchr (str
, '-');
2259 SETLOPORT(*portRange
, strtol(str
, &end
, 10));
2262 SETNUMPORTS(*portRange
, 1);
2266 /* Error in port range field. */
2267 errx (1, "unknown service %s/%s", str
, proto
);
2270 /* Port range, get the values and sanity check. */
2271 sscanf (str
, "%hu-%hu", &loPort
, &hiPort
);
2272 SETLOPORT(*portRange
, loPort
);
2273 SETNUMPORTS(*portRange
, 0); /* Error by default */
2274 if (loPort
<= hiPort
)
2275 SETNUMPORTS(*portRange
, hiPort
- loPort
+ 1);
2277 if (GETNUMPORTS(*portRange
) == 0)
2278 errx (1, "invalid port range %s", str
);
2284 int StrToProto (const char* str
)
2286 if (!strcmp (str
, "tcp"))
2289 if (!strcmp (str
, "udp"))
2292 errx (1, "unknown protocol %s. Expected tcp or udp", str
);
2295 int StrToAddrAndPortRange (const char* str
, struct in_addr
* addr
, char* proto
, port_range
*portRange
)
2299 ptr
= strchr (str
, ':');
2301 errx (1, "%s is missing port number", str
);
2306 StrToAddr (str
, addr
);
2307 return StrToPortRange (ptr
, proto
, portRange
);
2311 SetupPunchFW(const char *strValue
)
2313 unsigned int base
, num
;
2315 if (sscanf(strValue
, "%u:%u", &base
, &num
) != 2)
2316 errx(1, "punch_fw: basenumber:count parameter required");
2318 PacketAliasSetFWBase(base
, num
);
2319 (void)PacketAliasSetMode(PKT_ALIAS_PUNCH_FW
, PKT_ALIAS_PUNCH_FW
);