|
|
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.