Annotation of quakeworld/qwfwd/qwfwd.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.