1: /*
2:
3: The following is an interesting snippet of code I wrote recently. It
4: makes a data pipe between a listen port on the machine it's being run on
5: and a port on a remote machine. For example, running
6: datapipe 2222 23 your.machine.com
7:
8: would create a port 2222 on the local machine that, if telnetted to, would
9: be the same as telnetting to port 23 on your.machine.com. This can be used
10: for a variety of purposes: redirect IRC connections so that identd shows
11: the username of the datapipe process; redirect sendmail direct connections
12: for the same reason; even use on a firewall machine to give access to an
13: internal service (ftpd, for instance). Cascaded datapipes make for
14: interesting traceback dilemmas. Questions and comments accepted.
15:
16: Compile with:
17: cc -o datapipe -O datapipe.c
18: On boxes without strerror() (like SunOS 4.x), compile with:
19: cc -o datapipe -O -DSTRERROR datapipe.c
20:
21: Run as:
22: datapipe localport remoteport remotehost
23:
24: It will fork itself into the background.
25:
26: /*
27: * Datapipe - Create a listen socket to pipe connections to another
28: * machine/port. 'localport' accepts connections on the machine running
29: * datapipe, which will connect to 'remoteport' on 'remotehost'. Fairly
30: * standard 500 xxxx extended errors are used if something drastic
31: * happens.
32: *
33: * (c) 1995 Todd Vierling
34: *
35: * Define STRERROR while compiling on a SunOS 4.x box
36: */
37:
38: #include <sys/types.h>
39: #include <sys/socket.h>
40: #include <sys/wait.h>
41: #include <netinet/in.h>
42: #include <stdio.h>
43: #include <stdlib.h>
44: #include <errno.h>
45: #include <unistd.h>
46: #include <netdb.h>
47:
48: #include <linux/time.h>
49:
50: #ifdef STRERROR
51: extern char *sys_errlist[];
52: extern int sys_nerr;
53: char *undef = "Undefined error";
54:
55: char *strerror(error)
56: int error;
57: {
58: if (error > sys_nerr)
59: return undef;
60: return sys_errlist[error];
61: }
62: #endif
63:
64: main(argc, argv)
65: int argc;
66: char **argv;
67: {
68: int lsock, csock, osock;
69: FILE *cfile;
70: char buf[4096];
71: struct sockaddr_in laddr, caddr, oaddr;
72: int caddrlen = sizeof(caddr);
73: fd_set fdsr, fdse;
74: struct hostent *h;
75: struct servent *s;
76: int nbyt;
77: unsigned long a;
78: unsigned short oport;
79:
80: if (argc != 4) {
81: fprintf(stderr,"Usage: %s localport remoteport remotehost\n",argv[0]);
82: return 30;
83: }
84: a = inet_addr(argv[3]);
85: if (!(h = gethostbyname(argv[3])) &&
86: !(h = gethostbyaddr(&a, 4, AF_INET))) {
87: perror(argv[3]);
88: return 25;
89: }
90: oport = atol(argv[2]);
91: laddr.sin_port = htons((unsigned short)(atol(argv[1])));
92: if ((lsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
93: perror("socket");
94: return 20;
95: }
96: laddr.sin_family = htons(AF_INET);
97: laddr.sin_addr.s_addr = htonl(0);
98: if (bind(lsock, &laddr, sizeof(laddr))) {
99: perror("bind");
100: return 20;
101: }
102: if (listen(lsock, 1)) {
103: perror("listen");
104: return 20;
105: }
106: if ((nbyt = fork()) == -1) {
107: perror("fork");
108: return 20;
109: }
110: if (nbyt > 0)
111: return 0;
112: setsid();
113: while ((csock = accept(lsock, &caddr, &caddrlen)) != -1) {
114: cfile = fdopen(csock,"r+");
115: if ((nbyt = fork()) == -1) {
116: fprintf(cfile, "500 fork: %s\n", strerror(errno));
117: shutdown(csock,2);
118: fclose(cfile);
119: continue;
120: }
121: if (nbyt == 0)
122: goto gotsock;
123: fclose(cfile);
124: while (waitpid(-1, NULL, WNOHANG) > 0);
125: }
126: return 20;
127:
128: gotsock:
129: if ((osock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
130: fprintf(cfile, "500 socket: %s\n", strerror(errno));
131: goto quit1;
132: }
133: oaddr.sin_family = h->h_addrtype;
134: oaddr.sin_port = htons(oport);
135: memcpy(&oaddr.sin_addr, h->h_addr, h->h_length);
136: if (connect(osock, &oaddr, sizeof(oaddr))) {
137: fprintf(cfile, "500 connect: %s\n", strerror(errno));
138: goto quit1;
139: }
140: while (1) {
141: FD_ZERO(&fdsr);
142: FD_ZERO(&fdse);
143: FD_SET(csock,&fdsr);
144: FD_SET(csock,&fdse);
145: FD_SET(osock,&fdsr);
146: FD_SET(osock,&fdse);
147: if (select(20, &fdsr, NULL, &fdse, NULL) == -1) {
148: fprintf(cfile, "500 select: %s\n", strerror(errno));
149: goto quit2;
150: }
151: if (FD_ISSET(csock,&fdsr) || FD_ISSET(csock,&fdse)) {
152: if ((nbyt = read(csock,buf,4096)) <= 0)
153: goto quit2;
154: if ((write(osock,buf,nbyt)) <= 0)
155: goto quit2;
156: } else if (FD_ISSET(osock,&fdsr) || FD_ISSET(osock,&fdse)) {
157: if ((nbyt = read(osock,buf,4096)) <= 0)
158: goto quit2;
159: if ((write(csock,buf,nbyt)) <= 0)
160: goto quit2;
161: }
162: }
163:
164: quit2:
165: shutdown(osock,2);
166: close(osock);
167: quit1:
168: fflush(cfile);
169: shutdown(csock,2);
170: quit0:
171: fclose(cfile);
172: return 0;
173: }
|