/[rdesktop]/jpeg/rdpproxy/trunk/rdpproxy.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /jpeg/rdpproxy/trunk/rdpproxy.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1507 - (show annotations)
Mon Jul 20 16:45:11 2009 UTC (14 years, 9 months ago) by dpavlin
File MIME type: text/plain
File size: 18052 byte(s)
branch for integration of Daniel Jarboe <daniel.jarboe(at)gmail.com>
patches for jpeg
1 /* -*- c-basic-offset: 8 -*-
2 * rdpproxy: Man-in-the-middle RDP sniffer
3 * Matt Chapman <matthewc@cse.unsw.edu.au>
4 */
5
6 #define _GNU_SOURCE
7 #include <stdio.h> /* perror */
8 #include <string.h>
9 #include <unistd.h> /* select read write close */
10 #include <fcntl.h> /* open */
11 #include <sys/socket.h> /* socket bind listen accept connect */
12 #include <netinet/in.h> /* htons htonl */
13 #include <netinet/tcp.h> /* SOL_TCP TCP_NODELAY */
14 #include <arpa/inet.h> /* inet_addr */
15 #include <netdb.h> /* gethostbyname */
16
17 #include <openssl/x509v3.h>
18 #include "../rdesktop/rdesktop.h"
19
20 #if LINUX_NETFILTER
21 #include <linux/netfilter_ipv4.h>
22 #endif
23
24 #define CLIENT 0
25 #define SERVER 1
26
27 #define TCP_PORT_RDP 3389
28 #define SEC_ENCRYPT 0x0008
29 #define SEC_RANDOM_SIZE 32
30 #define SEC_MODULUS_SIZE 64
31 #define SEC_EXPONENT_SIZE 4
32
33 #ifdef USE_X509
34 #define CA_CERT_FILE "cacert.der"
35 #define CERT_FILE "cert.der"
36 #define PRIV_KEY_FILE "privkey.der"
37 #else
38 #define PRIV_KEY_FILE "tsprivkey.der"
39 #endif
40
41 static const unsigned char conn_response_hdr[] = { 0x02, 0xf0, 0x80, 0x7f, 0x66 };
42 #ifdef USE_X509
43 static const unsigned char cert_hdr[] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 };
44 static const unsigned char cert_hdr2[] = { 0x02, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00 };
45
46 static const unsigned char server_key_hdr[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x4b, 0x00 }; /* OID and ASN1 header */
47 static const unsigned char server_salt_hdr[] =
48 { SEC_RANDOM_SIZE, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00, 0x00 };
49 /* ^^^ seems to be 0x1e instead of 0x10 in "my" version of the protocol". It's some kind of length. */
50 static const unsigned char licence_blob_hdr[] = { 0x00, 0x00, 0x48, 0x00 }; /* not very precise, but hey */
51 #else
52 static const unsigned char server_key_hdr[] = { 'R', 'S', 'A', '1' };
53 static const unsigned char server_salt_hdr[] =
54 { SEC_RANDOM_SIZE, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00 };
55 #endif
56
57 static const unsigned char crypt_type_hdr[] = { 0x02, 0xc0, 0x0c, 0x00 };
58 static const unsigned char client_salt_hdr[] =
59 { 0x01, 0x00, 0x00, 0x00, SEC_MODULUS_SIZE + 8, 0x00, 0x00, 0x00 };
60
61
62 static unsigned char server_salt[SEC_RANDOM_SIZE];
63 static RSA *server_key;
64 static RSA *proxy_key;
65
66 static int server_key_subst_done;
67 static int client_key_subst_done;
68 static int compression_substs_done;
69 static int faked_packet;
70
71 void sec_decrypt(uint8 * data, int length);
72 void sec_encrypt(uint8 * data, int length);
73
74 /* produce a hex dump */
75 void
76 hexdump(unsigned char *p, int len)
77 {
78 unsigned char *line = p;
79 unsigned int thisline, offset = 0;
80 int i;
81
82 if (faked_packet)
83 {
84 printf("#0, #0 from Server, type TPKT, l: %d, faked\n", len);
85 faked_packet = 0;
86 }
87
88 while (offset < len)
89 {
90 printf("%04x ", offset);
91 thisline = len - offset;
92 if (thisline > 16)
93 thisline = 16;
94
95 for (i = 0; i < thisline; i++)
96 printf("%02x ", line[i]);
97
98 for (; i < 16; i++)
99 printf(" ");
100
101 for (i = 0; i < thisline; i++)
102 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
103
104 printf("\n");
105 offset += thisline;
106 line += thisline;
107 }
108 fflush(stdout);
109 }
110
111 /* reverse an array in situ */
112 static void
113 reverse(unsigned char *p, unsigned int len)
114 {
115 char temp;
116 int i, j;
117
118 for (i = 0, j = len - 1; i < j; i++, j--)
119 {
120 temp = p[i];
121 p[i] = p[j];
122 p[j] = temp;
123 }
124 }
125
126 static int
127 read_file(char *filename, char *buffer, int maxlen)
128 {
129 int fd, len;
130
131 fd = open(filename, O_RDONLY);
132 if (fd == -1)
133 {
134 perror(filename);
135 return -1;
136 }
137
138 len = read(fd, buffer, maxlen);
139 close(fd);
140 return len;
141 }
142
143 static RSA *
144 make_public_key(unsigned char *modulus, unsigned char *exponent)
145 {
146 BIGNUM *n, *e;
147 RSA *key;
148
149 n = BN_new();
150 reverse(modulus, SEC_MODULUS_SIZE);
151 BN_bin2bn(modulus, SEC_MODULUS_SIZE, n);
152
153 e = BN_new();
154 reverse(exponent, SEC_EXPONENT_SIZE);
155 BN_bin2bn(exponent, SEC_EXPONENT_SIZE, e);
156
157 key = RSA_new();
158 key->n = n;
159 key->e = e;
160 return key;
161
162 }
163
164 static void
165 substitute_client(unsigned char *buffer, unsigned int len)
166 {
167 unsigned char client_salt[SEC_RANDOM_SIZE];
168 unsigned char *key;
169
170 if (client_key_subst_done)
171 {
172 return;
173 }
174 else
175 {
176 printf("Client key substitution not done..\n");
177 }
178
179 /* temporary hack - pretend client asked for RDP4-type encryption */
180 if (!server_key_subst_done)
181 {
182 printf("Trying to substitute crypt type..\n");
183 key = memmem(buffer, len, crypt_type_hdr, sizeof(crypt_type_hdr));
184 if (key == NULL)
185 return;
186
187 key += sizeof(crypt_type_hdr);
188 *key = 1;
189 printf("Substituted crypt type\n");
190 return;
191 }
192
193 /* find client salt */
194 key = memmem(buffer, len, client_salt_hdr, sizeof(client_salt_hdr));
195 if (key == NULL)
196 {
197 printf("Didn't find client salt\n");
198 return;
199 }
200 else
201 {
202 printf("Found client salt(!)\n");
203 }
204
205 /* reencrypt with server key */
206 key += sizeof(client_salt_hdr);
207 reverse(key, SEC_MODULUS_SIZE);
208
209 printf("RSA_private_decrypt returns %d\n",
210 RSA_private_decrypt(SEC_MODULUS_SIZE, key, key,
211 proxy_key, RSA_NO_PADDING));
212
213 // printf("The 32 bytes before the client salt is:\n");
214 // faked_packet = 1;
215 // hexdump(key, SEC_MODULUS_SIZE-SEC_RANDOM_SIZE);
216
217 memcpy(client_salt, key + SEC_MODULUS_SIZE - SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
218 reverse(client_salt, SEC_RANDOM_SIZE);
219
220 RSA_public_encrypt(SEC_MODULUS_SIZE, key, key, server_key, RSA_NO_PADDING);
221 reverse(key, SEC_MODULUS_SIZE);
222
223 /* generate data encryption keys */
224 sec_generate_keys(client_salt, server_salt, 1);
225
226 printf("Substituted client salt\n");
227 client_key_subst_done = 1;
228 }
229
230 #ifdef USE_X509
231 static int licence_blob_subst_done;
232
233 static void
234 substitute_licence(unsigned char *buffer, unsigned int len)
235 {
236 unsigned char *key;
237
238 if (licence_blob_subst_done || !client_key_subst_done)
239 return;
240
241 key = memmem(buffer, len, licence_blob_hdr, sizeof(licence_blob_hdr));
242 if (key == NULL)
243 return;
244
245 /* reencrypt with server key */
246 key += sizeof(licence_blob_hdr);
247 reverse(key, SEC_MODULUS_SIZE);
248 RSA_private_decrypt(SEC_MODULUS_SIZE, key, key, proxy_key, RSA_NO_PADDING);
249
250 // hexdump(key, SEC_MODULUS_SIZE);
251
252 RSA_public_encrypt(SEC_MODULUS_SIZE, key, key, server_key, RSA_NO_PADDING);
253 reverse(key, SEC_MODULUS_SIZE);
254
255 printf("Substituted licence blob\n");
256 licence_blob_subst_done = 1;
257 }
258 #endif
259
260 static unsigned int
261 substitute_server(unsigned char *buffer, unsigned int len)
262 {
263 #ifndef USE_X509
264 unsigned char server_modulus[SEC_MODULUS_SIZE];
265 unsigned char server_exponent[SEC_EXPONENT_SIZE];
266 #endif
267 X509 *x509;
268 unsigned char *key, *rsakey;
269 unsigned char *mcslen_p;
270 unsigned char *userdata_length_p;
271 unsigned char *rem_length_p;
272 unsigned char *rsainfolen_p;
273 unsigned char *cryptinfo_len_p;
274 uint16 mcslen, userdata_length, rem_length;
275 uint32 cacert_len, cert_len;
276 int n, tag, delta;
277 uint16 length;
278 uint32 rsainfolen = 0;
279
280 if (server_key_subst_done)
281 return len;
282 key = memmem(buffer + 3, len - 3, conn_response_hdr, sizeof(conn_response_hdr));
283
284 if (NULL == key)
285 return len;
286
287 printf("Found MCS response packet\n");
288
289 mcslen_p = key + sizeof(conn_response_hdr) + 1;
290 mcslen = buf_in_uint16be(mcslen_p);
291
292 key += sizeof(conn_response_hdr) + 4 * 16;
293
294 rem_length_p = key - 2;
295 userdata_length_p = key - 25;
296
297 tag = *key + (*(key + 1) << 8);
298 key += 2;
299
300 while (tag != 0x0c02)
301 {
302 length = *key + (*(key + 1) << 8);
303 printf("Got length %x\n", length);
304 key += length - 2;
305 tag = *key + (*(key + 1) << 8);
306 key += 2;
307 }
308
309 length = *key + (*(key + 1) << 8);
310 printf("Got length %d\n", length);
311 cryptinfo_len_p = key; // Save position of cryptinfo length
312 key += 2 + 12; // Skip length, Skip RC4 key size, Encr. level, Random salt len, RSA info len.
313 rsainfolen = buf_in_uint32le(key);
314 rsainfolen_p = key; // Save position of RSA info len.
315 key += 4;
316 printf("RSA info len: %d\n", rsainfolen);
317
318 memcpy(server_salt, key, SEC_RANDOM_SIZE);
319
320 key += SEC_RANDOM_SIZE;
321
322 /* find RSA key structure */
323 rsakey = memmem(buffer, len, server_key_hdr, sizeof(server_key_hdr));
324 if (key == NULL)
325 return len;
326 printf("Found RSA key structure\n");
327
328
329 #ifdef USE_X509
330
331 /* extract server key */
332 /* rsakey += sizeof(server_key_hdr); */
333 /* server_key = d2i_RSAPublicKey(NULL, &rsakey, len-(rsakey-buffer)); */
334 /* printf("RSA_size(server_key): %d\n", RSA_size(server_key)); */
335 /* if (server_key == NULL) */
336 /* { */
337 /* printf("Error parsing public key\n"); */
338 /* return len; */
339 /* } */
340
341 key += 8;
342
343 cacert_len = buf_in_uint32le(key);
344 cert_len = buf_in_uint32le(key + cacert_len + 4);
345 rsakey = key + cacert_len + 8;
346 x509 = d2i_X509(NULL, &rsakey, cert_len);
347 if (NULL == x509)
348 {
349 printf("Failed to load X509 structure");
350 return len;
351 }
352
353 if (OBJ_obj2nid(x509->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
354 {
355 printf("Re-setting algorithm type to RSA ($#ยค?=## Microsoft!)\n");
356 x509->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
357 }
358
359 server_key = (RSA *) X509_get_pubkey(x509)->pkey.ptr;
360
361 /* This is a bit ugly. But who cares? :-) */
362
363 cacert_len = read_file(CA_CERT_FILE, key + 4, 1024);
364 *(unsigned long *) key = cacert_len; /* FIXME endianness */
365
366 key += 4 + cacert_len; // Skip length and newly "written" certificate.
367 cert_len = read_file(CERT_FILE, key + 4, 1024);
368 *(unsigned long *) key = cert_len; /* FIXME endianness */
369
370 printf("CA cert length is %d, cert length is %d\n", cacert_len, cert_len);
371
372 delta = (cacert_len + cert_len + 32) - rsainfolen;
373
374 if (0 < delta)
375 {
376 printf("Compensating RSA info len - should be %d\n", rsainfolen + delta);
377 buf_out_uint32(rsainfolen_p, rsainfolen + delta);
378 printf("Compensating Tagged data length - should be %d\n", length + delta);
379 buf_out_uint16le(cryptinfo_len_p, length + delta);
380 printf("Compensating MCS data length - should be %d\n", mcslen + delta);
381 buf_out_uint16be(mcslen_p, mcslen + delta);
382 printf("Compensating packet length - current value %d, should be %d\n",
383 len, len + delta);
384 len += delta;
385 buf_out_uint16be(buffer + 2, len);
386 printf("Padding with zeros at end of packet\n");
387 memset(buffer + len + delta - 16, 0, 16);
388
389 rem_length = buf_in_uint16be(rem_length_p) & ~0x8000;
390 buf_out_uint16be(rem_length_p, (rem_length + delta) | 0x8000);
391
392 userdata_length = buf_in_uint16be(userdata_length_p);
393 buf_out_uint16be(userdata_length_p, userdata_length + delta);
394
395 }
396 #else
397
398 /* extract server key */
399 rsakey += 16;
400 memcpy(server_exponent, rsakey, SEC_EXPONENT_SIZE);
401 rsakey += SEC_EXPONENT_SIZE;
402 memcpy(server_modulus, rsakey, SEC_MODULUS_SIZE);
403 server_key = make_public_key(server_modulus, server_exponent);
404
405 /* replace */
406 BN_bn2bin(proxy_key->n, rsakey);
407 reverse(rsakey, SEC_MODULUS_SIZE);
408 #endif
409
410 printf("Substituted server key\n");
411 faked_packet = 1;
412 server_key_subst_done = 1;
413
414 return len;
415 }
416
417 static void
418 decrypt(unsigned char *buffer, unsigned int len, void (*fn) (unsigned char *buffer, int length))
419 {
420 int encrypted = 0;
421 int skip;
422
423 if (buffer[0] == 3) /* ISO over TCP */
424 {
425 if (buffer[13] & 0x80) /* 16-bit length in MCS header */
426 skip = 15 + 12;
427 else
428 skip = 14 + 12;
429
430 if (len > skip)
431 encrypted = *(unsigned long *) (buffer + skip - 12) & SEC_ENCRYPT;
432 }
433 else /* assume RDP5 style packet */
434 {
435 if (buffer[1] & 0x80) /* 16-bit length */
436 skip = 3 + 8;
437 else
438 skip = 2 + 8;
439
440 if (len > skip)
441 encrypted = buffer[0] & 0x80;
442 }
443
444 if (encrypted)
445 {
446 if (client_key_subst_done)
447 fn(buffer + skip, len - skip);
448 else
449 printf("Can't decrypt, haven't seen client random!\n");
450 }
451
452 if (server_key_subst_done)
453 hexdump(buffer, len);
454 }
455
456 static void
457 substitute_compression(unsigned char *buffer, unsigned int len)
458 {
459 uint32 flags, packetflags;
460
461
462 if (compression_substs_done)
463 return;
464 if (!(buffer[7] & 0x64))
465 { /* Not a MCS SDRQ - actually quite a
466 useless check since this function isn't
467 called unless the packet is from the client */
468 return;
469 }
470
471 packetflags = buf_in_uint32le(buffer + 15);
472 if (!(packetflags & 0x0040))
473 return; /* Not a RDP Logon info packet */
474
475 flags = buf_in_uint32le(buffer + 31);
476
477 printf("Found the RDP Logon packet, flags is %d (%x)\n", flags, flags);
478
479 if (flags & 0x280)
480 {
481 printf("Setting compression flags to zero\n");
482 flags &= ~0x280;
483
484 buf_out_uint32(buffer + 31, flags);
485
486 }
487 printf("Flags is now %d (%x)\n", flags, flags);
488
489 compression_substs_done = 1;
490 }
491
492 static void
493 decrypt_client(unsigned char *buffer, unsigned int len, int server)
494 {
495
496 int encrypted = 0;
497 int skip;
498 unsigned char buffercopy[65536];
499 uint8 signature[8];
500
501 if (buffer[0] == 3) /* ISO over TCP */
502 {
503 if (buffer[13] & 0x80) /* 16-bit length in MCS header */
504 skip = 15 + 12;
505 else
506 skip = 14 + 12;
507
508 if (len > skip)
509 encrypted = *(unsigned long *) (buffer + skip - 12) & SEC_ENCRYPT;
510 }
511 else /* assume RDP5 style packet */
512 {
513 if (buffer[1] & 0x80) /* 16-bit length */
514 skip = 3 + 8;
515 else
516 skip = 2 + 8;
517
518 if (len > skip)
519 encrypted = buffer[0] & 0x80;
520 }
521
522 substitute_client(buffer, len);
523
524
525 if (encrypted && client_key_subst_done)
526 {
527 sec_encrypt(buffer + skip, len - skip);
528 memset(signature, 0, 8);
529
530 /* This is where you can put substitution code */
531
532 substitute_compression(buffer, len);
533
534 #ifdef USE_X509
535 substitute_licence(buffer, len);
536 #endif
537 sec_sign_buf(signature, 8, buffer + skip, len - skip);
538 printf("Signature should be ");
539 hexdump(signature, 8);
540 hexdump(buffer, len);
541 memcpy(buffer + skip - 8, signature, 8);
542 sec_encrypt2(buffer + skip, len - skip);
543 }
544 else
545 {
546 printf("Can't decrypt, haven't seen client random!\n");
547 hexdump(buffer, len);
548 }
549
550 send(server, buffer, len, 0);
551
552
553 }
554
555 static int
556 recv_pdu(int fd, unsigned char *buffer, unsigned int len, int part)
557 {
558 unsigned int pdulen;
559 int res;
560
561 static int clnt_packetnr;
562 static int srvr_packetnr;
563 static int total_packetnr;
564
565 res = recv(fd, buffer, 4, MSG_WAITALL);
566 if (res <= 0)
567 return res;
568
569 if (CLIENT == part)
570 {
571 printf("#%d, #%d from Client, ", ++total_packetnr, ++clnt_packetnr);
572 }
573 else
574 {
575 printf("#%d, #%d from Server, ", ++total_packetnr, ++srvr_packetnr);
576 }
577
578
579 if (buffer[0] == 3) /* ISO over TCP */
580 {
581 pdulen = ((unsigned int) buffer[2] << 8) | buffer[3];
582 printf("type TPKT, l: %d, ", pdulen);
583
584 }
585 else /* assume RDP5 style packet */
586 {
587 pdulen = buffer[1];
588
589 if (pdulen & 0x80)
590 pdulen = ((pdulen & 0x7f) << 8) | buffer[2];
591 printf("type RDP5, l: %d, ", pdulen);
592 }
593
594 if (pdulen > len)
595 {
596 fprintf(stderr, "PDU size %d would overflow buffer\n", pdulen);
597 return 0;
598 }
599
600 res = recv(fd, buffer + 4, pdulen - 4, MSG_WAITALL);
601 if (res <= 0)
602 return res;
603
604 printf("read %d bytes\n", res + 4);
605
606 return (res + 4);
607 }
608
609 static void
610 relay(int client, int server)
611 {
612 unsigned char buffer[65536];
613 fd_set fds;
614 int max, len;
615
616 FD_ZERO(&fds);
617 max = (client > server) ? client : server;
618
619 while (1)
620 {
621 FD_SET(client, &fds);
622 FD_SET(server, &fds);
623
624 switch (select(max + 1, &fds, NULL, NULL, NULL))
625 {
626 case -1:
627 perror("select");
628
629 case 0:
630 return;
631 }
632
633 if (FD_ISSET(client, &fds))
634 {
635 len = recv_pdu(client, buffer, sizeof(buffer), CLIENT);
636 switch (len)
637 {
638 case -1:
639 perror("client recv");
640 case 0:
641 return;
642 }
643
644 decrypt_client(buffer, len, server);
645 }
646
647 if (FD_ISSET(server, &fds))
648 {
649 len = recv_pdu(server, buffer, sizeof(buffer), SERVER);
650 switch (len)
651 {
652 case -1:
653 perror("server recv");
654 case 0:
655 return;
656 }
657 if (!server_key_subst_done)
658 {
659 hexdump(buffer, len);
660 }
661 len = substitute_server(buffer, len);
662 send(client, buffer, len, 0);
663 decrypt(buffer, len, sec_decrypt);
664 }
665 }
666 }
667
668 int
669 main(int argc, char *argv[])
670 {
671 struct sockaddr_in listener_addr;
672 struct sockaddr_in server_addr;
673 struct hostent *nslookup;
674 int listener, client, server;
675 unsigned char privkey_buffer[1024];
676 unsigned char *privkey = privkey_buffer;
677 int true = 1;
678 int n;
679
680 #ifndef LINUX_NETFILTER
681 if (argc < 2)
682 {
683 printf("Usage: rdpproxy <server ip>\n");
684 return 1;
685 }
686 #endif
687
688 n = read_file(PRIV_KEY_FILE, privkey_buffer, sizeof(privkey_buffer));
689
690
691
692 proxy_key = d2i_RSAPrivateKey(NULL, &privkey, n);
693 memset(privkey_buffer, 0, sizeof(privkey_buffer));
694 if (proxy_key == NULL)
695 {
696 printf("Error loading private key\n");
697 return 1;
698 }
699
700 if ((listener = socket(AF_INET, SOCK_STREAM, 0)) < 0)
701 {
702 perror("socket");
703 return 1;
704 }
705
706 listener_addr.sin_family = AF_INET;
707 listener_addr.sin_port = htons(TCP_PORT_RDP);
708 listener_addr.sin_addr.s_addr = htonl(INADDR_ANY);
709
710 setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(true));
711
712 if (bind(listener, (struct sockaddr *) &listener_addr, sizeof(listener_addr)) < 0)
713 {
714 perror("bind");
715 return 1;
716 }
717
718 if (listen(listener, 1) < 0)
719 {
720 perror("listen");
721 return 1;
722 }
723
724 printf("RDPPROXY: waiting for connection...\n");
725
726 if ((client = accept(listener, NULL, NULL)) < 0)
727 {
728 perror("accept");
729 return 1;
730 }
731
732 if ((server = socket(AF_INET, SOCK_STREAM, 0)) < 0)
733 {
734 perror("socket");
735 return 1;
736 }
737
738 server_addr.sin_family = AF_INET;
739 server_addr.sin_port = htons(TCP_PORT_RDP);
740
741 #ifdef LINUX_NETFILTER
742 if (argc < 2)
743 {
744 /* Fetch server address from netfilter */
745 size_t sock_sz;
746 sock_sz = sizeof(server_addr);
747
748 if (getsockopt(client, SOL_IP, SO_ORIGINAL_DST, &server_addr, &sock_sz) != 0)
749 {
750 perror("getsockopt");
751 fprintf(stderr, "Not a redirected connection?\n");
752 exit(1);
753 }
754
755 fprintf(stderr, "server IP = %s\n", inet_ntoa(server_addr.sin_addr));
756 }
757 else
758 #endif
759 {
760 /* Use server name from command line */
761 if (NULL != (nslookup = gethostbyname(argv[1])))
762 {
763 memcpy(&server_addr.sin_addr, nslookup->h_addr,
764 sizeof(server_addr.sin_addr));
765 }
766 else if (INADDR_NONE == (server_addr.sin_addr.s_addr = inet_addr(argv[1])))
767 {
768 printf("%s: Unable to resolve host\n", argv[1]);
769 return 1;
770 }
771 }
772
773 if (connect(server, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)
774 {
775 perror("connect");
776 return 1;
777 }
778
779 setsockopt(client, SOL_TCP, TCP_NODELAY, &true, sizeof(true));
780 setsockopt(server, SOL_TCP, TCP_NODELAY, &true, sizeof(true));
781
782 relay(client, server);
783
784 close(server);
785 close(client);
786 return 0;
787 }

  ViewVC Help
Powered by ViewVC 1.1.26