forked from proxytunnel/proxytunnel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
io.c
143 lines (121 loc) · 4.29 KB
/
io.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* Proxytunnel - (C) 2001-2008 Jos Visser / Mark Janssen */
/* Contact: josv@osp.nl / maniac@maniac.nl */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* io.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "proxytunnel.h"
#include "io.h"
#define ACTIVE 1
#define CLOSED 0
/*
* Read one line of data from the tunnel. Line is terminated by a
* newline character. Result is stored in buf.
*/
int readline(PTSTREAM *pts) {
char *p = buf;
char c = 0;
int i = 0;
/* Read one character at a time into buf, until a newline is encountered. */
while ( c != 10 && ( i < SIZE - 1 ) ) {
if( stream_read( pts, &c ,1) <= 0) {
my_perror( "Socket read error" );
exit( 1 );
}
*p = c;
p++;
i++;
}
*p = 0;
if( args_info.verbose_flag ) {
/* Copy line of data into dstr without trailing newline */
char *dstr = malloc(strlen(buf) + 1);
strncpy( dstr, buf, strlen(buf));
if (strcmp(dstr, ""))
message( " <- %s\n", dstr );
}
return strlen( buf );
}
/*
* Bond stream1 and stream2 together; any data received in stream1 is relayed
* to stream2, and vice-versa.
*/
void cpio(PTSTREAM *stream1, PTSTREAM *stream2) {
fd_set readfds;
fd_set writefds;
fd_set exceptfds;
int in_max_fd, out_max_fd, max_fd;
/* Find the biggest file descriptor for select() */
in_max_fd = MAX(stream_get_incoming_fd(stream1), stream_get_incoming_fd(stream2));
out_max_fd = MAX(stream_get_outgoing_fd(stream1), stream_get_outgoing_fd(stream2));
max_fd = MAX(in_max_fd, out_max_fd);
/* We are never interested in sockets being available for write */
FD_ZERO( &writefds );
/* experimental timeout */
struct timeval select_timeout;
select_timeout.tv_sec = 30; /* should be fine */
select_timeout.tv_usec = 0;
if( args_info.verbose_flag )
message( "\nTunnel established.\n" );
int stream_status = ACTIVE;
while( stream_status == ACTIVE ) {
/* Clear the interesting socket sets */
FD_ZERO( &readfds );
FD_ZERO( &exceptfds );
/* We want to know whether stream1 or stream2 is ready for reading */
FD_SET( stream_get_incoming_fd(stream1), &readfds );
FD_SET( stream_get_incoming_fd(stream2), &readfds );
/* And we want to know about exceptional conditions on either stream */
FD_SET( stream_get_incoming_fd(stream1), &exceptfds );
FD_SET( stream_get_outgoing_fd(stream1), &exceptfds );
FD_SET( stream_get_incoming_fd(stream2), &exceptfds );
FD_SET( stream_get_outgoing_fd(stream2), &exceptfds );
/* reset the timeout, since select() does modify this struct! */
select_timeout.tv_sec = 30;
select_timeout.tv_usec = 0;
/* Wait/timeout something happens on the registered sockets/files */
int number_of_fds_ready;
number_of_fds_ready = select( max_fd + 1, &readfds, &writefds, &exceptfds, &select_timeout );
if ( number_of_fds_ready < 0 ) {
perror("select error");
exit(1);
}
if (number_of_fds_ready > 0) {
/* Is stream1 ready for read? If so, copy a block of data
* from stream1 to stream2. Or else if stream2
* is ready for read, copy a block of data from the
* stream2 to stream1. Otherwise an exceptional condition
* is flagged and the program is terminated.
*/
if ( FD_ISSET( stream_get_incoming_fd(stream1), &readfds ) ) {
if ( stream_copy(stream1, stream2 ) )
stream_status = CLOSED;
} else if( FD_ISSET( stream_get_incoming_fd(stream2), &readfds ) ) {
if( stream_copy(stream2, stream1 ) )
stream_status = CLOSED;
} else {
my_perror( "Exceptional condition" );
stream_status = CLOSED;
}
}
}
closeall();
}