1 /*
2 * (c) Copyright 1998-2001 by Rob Braun
3 * All rights reserved. The file named COPYRIGHT specifies the terms
4 * and conditions for redistribution.
5 */
6 #include "config.h"
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include <sys/time.h>
10 #ifdef HAVE_SYS_RESOURCE_H
11 #include <sys/resource.h>
12 #endif
13 #include <sys/wait.h>
14 #include <netinet/in.h>
15 #include <errno.h>
16 #include <pwd.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <sys/wait.h>
20 #include <signal.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <netinet/tcp.h>
24 #ifdef HAVE_ARPA_INET_H
25 #include <arpa/inet.h>
26 #endif
27 #ifdef HAVE_SYS_SIGNAL_H
28 #include <sys/signal.h>
29 #endif
30
31 #include "redirect.h"
32 #include "service.h"
33 #include "log.h"
34 #include "sconf.h"
35 #include "msg.h"
36
37 #define NET_BUFFER 1500
38
39 static int RedirServerFd = -1;
40
41 /* Theoretically, this gets invoked when the remote side is no
42 * longer available for reading or writing.
43 * So, we send a HUP to the child process, wait(), then exit.
44 */
45 #ifdef __GNUC__
46 __attribute__ ((noreturn))
47 #endif
redir_sigpipe(int signum)48 static void redir_sigpipe( int signum )
49 {
50 Sclose(RedirServerFd);
51 _exit(0);
52 }
53
54 /* Do the redirection of a service */
55 /* This function gets called from child.c after we have been forked */
redir_handler(struct server * serp)56 void redir_handler( struct server *serp )
57 {
58 struct service *sp = SERVER_SERVICE( serp );
59 struct service_config *scp = SVC_CONF( sp );
60 int RedirDescrip = SERVER_FD( serp );
61 int maxfd;
62 ssize_t num_read, num_wrote=0, ret=0;
63 unsigned int sin_len = 0;
64 unsigned long bytes_in = 0, bytes_out = 0;
65 int no_to_nagle = 1;
66 int on = 1, v6on;
67 char buff[NET_BUFFER];
68 fd_set rdfd, msfd;
69 struct timeval *timep = NULL;
70 const char *func = "redir_handler";
71 union xsockaddr serveraddr ;
72
73 if( signal(SIGPIPE, redir_sigpipe) == SIG_ERR )
74 msg(LOG_ERR, func, "unable to setup signal handler");
75
76 close_all_svc_descriptors();
77
78 /* If it's a tcp service we are redirecting */
79 if( SC_PROTOVAL(scp) == IPPROTO_TCP )
80 {
81 memcpy(&serveraddr, SC_REDIR_ADDR(scp), sizeof(serveraddr));
82 if( serveraddr.sa_in.sin_family == AF_INET ) {
83 sin_len = sizeof( struct sockaddr_in );
84 RedirServerFd = socket(AF_INET, SOCK_STREAM, 0);
85 } else if( serveraddr.sa_in.sin_family == AF_INET6 ) {
86 sin_len = sizeof( struct sockaddr_in6 );
87 RedirServerFd = socket(AF_INET6, SOCK_STREAM, 0);
88 } else {
89 msg(LOG_ERR, func, "not a valid protocol. Use IPv4 or IPv6.");
90 exit(0);
91 }
92
93 if( RedirServerFd < 0 )
94 {
95 msg(LOG_ERR, func, "cannot create socket: %m");
96 exit(0);
97 }
98
99 if( SC_IPV6( scp ) ) {
100 if( SC_V6ONLY( scp ) ) {
101 v6on = 1;
102 } else {
103 v6on = 0;
104 }
105 #ifdef IPV6_V6ONLY
106 if( setsockopt(RedirServerFd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6on, sizeof(v6on)) < 0 ) {
107 msg( LOG_ERR, func, "Setting IPV6_V6ONLY option failed (%m)" );
108 }
109 #endif
110
111 }
112 if( SC_KEEPALIVE( scp ) )
113 if (setsockopt(RedirServerFd, SOL_SOCKET, SO_KEEPALIVE,
114 (char *)&on, sizeof( on ) ) < 0 )
115 msg(LOG_ERR, func,
116 "setsockopt SO_KEEPALIVE RedirServerFd failed: %m");
117
118 if( serveraddr.sa_in.sin_family == AF_INET )
119 serveraddr.sa_in.sin_port = htons(serveraddr.sa_in.sin_port);
120 if( serveraddr.sa_in.sin_family == AF_INET6 )
121 serveraddr.sa_in6.sin6_port = htons(serveraddr.sa_in6.sin6_port);
122
123 if( connect(RedirServerFd, &serveraddr.sa, sin_len) < 0 )
124 {
125 msg(LOG_ERR, func, "can't connect to remote host %s: %m",
126 xaddrname( &serveraddr ) );
127 exit(0);
128 }
129
130 /* connection now established */
131
132 if (setsockopt(RedirServerFd, IPPROTO_TCP, TCP_NODELAY,
133 (char *) &no_to_nagle, sizeof( on ) ) < 0) {
134
135 msg(LOG_ERR, func, "setsockopt RedirServerFd failed: %m");
136 }
137
138 if (setsockopt(RedirDescrip, IPPROTO_TCP, TCP_NODELAY,
139 (char *) &no_to_nagle, sizeof( on ) ) < 0) {
140
141 msg(LOG_ERR, func, "setsockopt RedirDescrip failed: %m");
142 }
143
144 maxfd = (RedirServerFd > RedirDescrip)?RedirServerFd:RedirDescrip;
145 FD_ZERO(&msfd);
146 FD_SET(RedirDescrip, &msfd);
147 FD_SET(RedirServerFd, &msfd);
148
149 while(1) {
150 memcpy(&rdfd, &msfd, sizeof(rdfd));
151 if (select(maxfd + 1, &rdfd, (fd_set *)0, (fd_set *)0, timep) <= 0) {
152 /* place for timeout code, currently does not time out */
153 break;
154 }
155
156 if (FD_ISSET(RedirDescrip, &rdfd)) {
157 do {
158 num_read = read(RedirDescrip,
159 buff, sizeof(buff));
160 if (num_read == (ssize_t)-1 && errno == EINTR)
161 continue;
162 if (num_read <= 0)
163 goto REDIROUT;
164 bytes_in += num_read;
165 } while (num_read < 0);
166
167 /* Loop until we have written everything
168 * that was read */
169 num_wrote = 0;
170 while( num_wrote < num_read ) {
171 ret = write(RedirServerFd,
172 buff + num_wrote,
173 num_read - num_wrote);
174 if (ret == -1 && errno == EINTR)
175 continue;
176 if (ret <= 0)
177 goto REDIROUT;
178 num_wrote += ret;
179 }
180 }
181
182 if (FD_ISSET(RedirServerFd, &rdfd)) {
183 do {
184 num_read = read(RedirServerFd,
185 buff, sizeof(buff));
186 if (num_read == -1 && errno == EINTR)
187 continue;
188 if (num_read <= 0)
189 goto REDIROUT;
190 bytes_out += num_read;
191 } while (num_read < 0);
192
193 /* Loop until we have written everything
194 * that was read */
195 num_wrote = 0;
196 while( num_wrote < num_read ) {
197 ret = write(RedirDescrip,
198 buff + num_wrote,
199 num_read - num_wrote);
200 if (ret == -1 && errno == EINTR)
201 continue;
202 if (ret <= 0)
203 goto REDIROUT;
204 num_wrote += ret;
205 }
206 }
207 }
208 REDIROUT:
209 if( M_IS_SET( SC_LOG_ON_SUCCESS(scp), LO_TRAFFIC ) ) {
210 svc_logprint( SERVER_CONNSERVICE( serp ), "TRAFFIC",
211 "in=%lu(bytes) out=%lu(bytes)", bytes_in, bytes_out );
212 }
213
214 exit(0);
215 }
216
217 msg(LOG_ERR, func,
218 "redirect with any protocol other than tcp is not supported at this time.");
219 exit(0);
220 }
221