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