|
|
1.1 root 1: /*
2: Copyright (C) 1996-1997 Id Software, Inc.
3:
4: This program is free software; you can redistribute it and/or
5: modify it under the terms of the GNU General Public License
6: as published by the Free Software Foundation; either version 2
7: of the License, or (at your option) any later version.
8:
9: This program is distributed in the hope that it will be useful,
10: but WITHOUT ANY WARRANTY; without even the implied warranty of
11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12:
13: See the GNU General Public License for more details.
14:
15: You should have received a copy of the GNU General Public License
16: along with this program; if not, write to the Free Software
17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18:
19: */
20:
21:
22: /*
23: * udpred - a inetd launched udp port redirector
24: *
25: * Version: @(#)udpred.c 0.01 01/15/97
26: *
27: * Author: Chris Faherty <[email protected]>
28: *
29: * syntax:
30: *
31: * udpred toip toport
32: *
33: * sample inetd.conf entry:
34: *
35: * 7000 dgram udp wait root /usr/sbin/tcpd /usr/sbin/udpred 192.168.100.16 7000
36: *
37: *
38: * This program is free software; you can redistribute it and/or
39: * modify it under the terms of the GNU General Public License
40: * as published by the Free Software Foundation; either version
41: * 2 of the License, or (at your option) any later version.
42: *
43: */
44: #include <stdio.h>
45: #include <errno.h>
46: #include <fcntl.h>
47: #include <signal.h>
48: #include <stdlib.h>
49: #include <sys/types.h>
50: #include <time.h>
51:
52: #ifdef _WIN32
53: #include <winsock.h>
54: #else
55: #include <sys/time.h>
56: #include <sys/socket.h>
57: #include <sys/wait.h>
58: #include <netdb.h>
59: #include <netinet/in.h>
60: #include <unistd.h>
61: #include <syslog.h>
62:
63: #endif
64:
65: int host_port; // port we are listening on
66:
67: typedef struct peer {
68: time_t last;
69: struct sockaddr_in sin;
70: struct sockaddr_in dest;
71: int s; // connected socket to remote
72: struct peer *next;
73: } peer_t;
74:
75: peer_t *peers;
76:
77: /*
78: ====================
79: NET_Init
80: ====================
81: */
82: void NET_Init (void)
83: {
84: #ifdef _WIN32
85: static WSADATA winsockdata;
86: // WORD wVersionRequested;
87: int r;
88:
89: // wVersionRequested = MAKEWORD(1, 1);
90:
91: r = WSAStartup (MAKEWORD(2, 1), &winsockdata);
92:
93: if (r) {
94: fprintf(stderr, "Winsock initialization failed.");
95: exit(1);
96: }
97:
98: printf("Winsock Initialized\n");
99: #endif
100: }
101:
102:
103:
104: int connectsock(char *host, char *service, char *protocol)
105: {
106: struct hostent *phe;
107: struct servent *pse;
108: struct protoent *ppe;
109: struct sockaddr_in sin;
110: int s, type;
111:
112: memset(&sin, 0, sizeof(sin));
113: sin.sin_family = AF_INET;
114:
115: /* Map service name to port number */
116: if(pse = getservbyname(service, protocol))
117: sin.sin_port = pse->s_port;
118: else if((sin.sin_port = htons((u_short)atoi(service))) == 0)
119: {
120: fprintf(stderr, "udpred: can't get \"%s\" service entry\n", service);
121: exit(2);
122: }
123:
124: /* Map host name to IP address, allowing for dotted decimal */
125: if(phe = gethostbyname(host))
126: memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
127: else if((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
128: {
129: fprintf(stderr, "udpred: can't get \"%s\" host entry\n", host);
130: exit(2);
131: }
132:
133: /* Map protocol name to protocol number */
134: if((ppe = getprotobyname(protocol)) == 0)
135: {
136: fprintf(stderr, "udpred: can't get \"%s\" protocol entry\n", protocol);
137: exit(2);
138: }
139:
140: /* Use protocol to choose a socket type */
141: if(strcmp(protocol, "udp") == 0)
142: type = SOCK_DGRAM;
143: else
144: type = SOCK_STREAM;
145:
146: /* Allocate a socket */
147: s = socket(PF_INET, type, ppe->p_proto);
148: if(s < 0)
149: {
150: fprintf(stderr, "udpred: can't create socket: %s\n", sys_errlist[errno]);
151: exit(2);
152: }
153:
154: /* Connect the socket */
155: if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
156: {
157: fprintf(stderr, "udpred: can't connect to %s.%s: %s\n", host, service, sys_errlist[errno]);
158: exit(2);
159: }
160: return s;
161: }
162:
163: int main(int argc, char *argv[])
164: {
165: fd_set rfds;
166: struct timeval tv;
167: int retval;
168: int i1;
169: char buffer[4095];
170: struct sockaddr_in fsin;
171: int alen;
172: peer_t *p;
173: int s;
174: struct sockaddr_in address;
175:
176: if (argc < 3) {
177: printf("Usage: %s <port> <remote server> <remote server port>\n", argv[0]);
178: return 1;
179: }
180:
181: NET_Init();
182:
183: if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
184: perror("socket");
185: return 1;
186: }
187:
188: address.sin_family = AF_INET;
189: address.sin_addr.s_addr = INADDR_ANY;
190: address.sin_port = htons((unsigned short)atoi(argv[1]));
191: if (bind (s, (void *)&address, sizeof(address)) == -1)
192: perror("bind");
193:
194: while(1)
195: {
196: FD_ZERO(&rfds);
197: FD_SET(s, &rfds);
198: i1 = s;
199: for (p = peers; p; p = p->next) {
200: FD_SET(p->s, &rfds);
201: if (p->s >= i1)
202: i1 = p->s + 1;
203: }
204: /* Wait up to two minutes. */
205: tv.tv_sec = 2;
206: tv.tv_usec = 0;
207: retval = select(i1, &rfds, (fd_set *)0, (fd_set *)0, &tv);
208: if(retval > 0)
209: {
210: if(FD_ISSET(s, &rfds))
211: {
212: alen = sizeof(fsin);
213: i1 = recvfrom(s, buffer, 4096, 0, (struct sockaddr *) &fsin, &alen);
214: if(i1 > 0) {
215: for (p = peers; p; p = p->next)
216: if (memcmp(&p->sin.sin_addr, &fsin.sin_addr, sizeof(p->sin.sin_addr)) == 0 &&
217: memcmp(&p->sin.sin_port, &fsin.sin_port, sizeof(p->sin.sin_port)) == 0)
218: {
219: send(p->s, buffer, i1, 0);
220: time(&p->last);
221: break;
222: }
223: if (p == NULL) { // new peer
224: printf("peer %s:%d added", inet_ntoa(fsin.sin_addr), (int)ntohs(fsin.sin_port));
225: p = malloc(sizeof *p);
226: p->sin = fsin;
227: p->s = connectsock(argv[2], argv[3], "udp");
228: p->next = peers;
229: peers = p;
230: send(p->s, buffer, i1, 0);
231: time(&p->last);
232: }
233: }
234: }
235: for (p = peers; p; p = p->next)
236: if(FD_ISSET(p->s, &rfds))
237: {
238: i1 = recv(p->s, buffer, 4096, 0);
239: if(i1 > 0) {
240: time(&p->last);
241: sendto(s, buffer, i1, 0, (struct sockaddr *) &p->sin,
242: sizeof(p->sin));
243: }
244: }
245: } else {
246: peer_t *pp;
247:
248: pp = NULL;
249: p = peers;
250: while (p) {
251: if (time(NULL) - p->last > 300) {
252: if (!pp && !p->next) {
253: printf("peer %s:%d removed (timeout)", inet_ntoa(p->sin.sin_addr), (int)ntohs(p->sin.sin_port));
254: free(p);
255: p = pp = NULL;
256: continue;
257: }
258: pp->next = p->next;
259: printf ("peer %s:%d removed (timeout)", inet_ntoa(p->sin.sin_addr), (int)ntohs(p->sin.sin_port));
260: free(p);
261: p = pp->next;
262: } else {
263: pp = p;
264: p = p->next;
265: }
266: }
267: }
268: }
269: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.