up io error count if not exiting
[tridge/junkcode.git] / udpproxy.c
1 #define _GNU_SOURCE
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <time.h>
7 #include <errno.h>
8 #include <sys/socket.h>
9 #include <netdb.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <fcntl.h>
13 #include <sys/types.h>
14 #include <sys/time.h>
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
17 #include <signal.h>
18
19 #define MAX(a,b) ((a)>(b)?(a):(b))
20
21 /* open a socket to a remote host with the specified port */
22 static int open_socket_out(const char *host, int port)
23 {
24         struct sockaddr_in sock_out;
25         int res;
26         struct hostent *hp;  
27         struct in_addr addr;
28
29         res = socket(PF_INET, SOCK_DGRAM, 0);
30         if (res == -1) {
31                 return -1;
32         }
33
34         if (inet_pton(AF_INET, host, &addr) > 0) {
35                 memcpy(&sock_out.sin_addr, &addr, sizeof(addr));
36         } else {
37                 hp = gethostbyname(host);
38                 if (!hp) {
39                         fprintf(stderr,"unknown host %s\n", host);
40                         return -1;
41                 }
42                 memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
43         }
44
45         sock_out.sin_port = htons(port);
46         sock_out.sin_family = PF_INET;
47
48         if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)) != 0) {
49                 close(res);
50                 fprintf(stderr,"failed to connect to %s (%s)\n", 
51                         host, strerror(errno));
52                 return -1;
53         }
54
55         return res;
56 }
57
58
59 /*
60   open a socket of the specified type, port and address for incoming data
61 */
62 int open_socket_in(int port)
63 {
64         struct sockaddr_in sock;
65         int res;
66         int one=1;
67
68         memset(&sock,0,sizeof(sock));
69
70 #ifdef HAVE_SOCK_SIN_LEN
71         sock.sin_len = sizeof(sock);
72 #endif
73         sock.sin_port = htons(port);
74         sock.sin_family = AF_INET;
75
76         res = socket(AF_INET, SOCK_DGRAM, 0);
77         if (res == -1) { 
78                 fprintf(stderr, "socket failed\n"); return -1; 
79                 return -1;
80         }
81
82         setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
83
84         if (bind(res, (struct sockaddr *)&sock, sizeof(sock)) < 0) { 
85                 return(-1); 
86         }
87
88         return res;
89 }
90
91 /* write to a file descriptor, making sure we get all the data out or
92  * die trying */
93 static void write_all(int fd, unsigned char *s, size_t n)
94 {
95         usleep(1000);
96         while (n) {
97                 int r;
98                 r = write(fd, s, n);
99                 if (r <= 0) {
100                         exit(1);
101                 }
102                 s += r;
103                 n -= r;
104         }
105 }
106
107 static void main_loop(int sock1, int sock2)
108 {
109         unsigned char buf[10240];
110         int i=0;
111         static struct sockaddr from;
112         static socklen_t fromlen = sizeof(from);
113
114         while (1) {
115                 fd_set fds;
116                 int ret;
117
118                 FD_ZERO(&fds);
119                 FD_SET(sock1, &fds);
120                 FD_SET(sock2, &fds);
121
122                 ret = select(MAX(sock1, sock2)+1, &fds, NULL, NULL, NULL);
123                 if (ret == -1 && errno == EINTR) continue;
124                 if (ret <= 0) break;
125
126                 if (FD_ISSET(sock1, &fds)) {
127                         int n = recvfrom(sock1, buf, sizeof(buf), 0, &from, &fromlen);
128                         if (n <= 0) break;
129
130 //                      printf("out %d bytes\n", n);
131                         write_all(sock2, buf, n);
132                 }
133
134                 if (FD_ISSET(sock2, &fds)) {
135                         int n = read(sock2, buf, sizeof(buf));
136                         if (n <= 0) break;
137
138 //                      printf("in %d bytes\n", n);
139                         sendto(sock1, buf, n, 0, &from, fromlen);
140                 }
141         }       
142 }
143
144 static int sig_alrm(int sig)
145 {
146         return 0;
147 }
148
149 int main(int argc, char *argv[])
150 {
151         int listen_port, dest_port;
152         char *host;
153         int sock_in;
154         int sock_out;
155         struct sockaddr addr;
156         int in_addrlen = sizeof(addr);
157         char buf[8192];
158
159         if (argc < 4) {
160                 printf("Usage: sockspy <inport> <host> <port>\n");
161                 exit(1);
162         }
163
164         listen_port = atoi(argv[1]);
165         host = argv[2];
166         dest_port = atoi(argv[3]);
167
168         sock_in = open_socket_in(listen_port);
169
170         if (sock_in == -1) {
171                 fprintf(stderr,"sock on port %d failed - %s\n", 
172                         listen_port, strerror(errno));
173                 exit(1);
174         }
175
176         signal(SIGCHLD, SIG_IGN);
177
178         signal(SIGALRM, sig_alrm);
179
180         sock_out = open_socket_out(host, dest_port);
181
182         main_loop(sock_in, sock_out);
183
184         return 0;
185 }