/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. VMS port by Andrew Molitor. */ #ifndef lint static char RCSid[] = "$Header: /usr/users/mjr/hacks/umud/RCS/xmit_bsd.c,v 1.1 91/06/17 14:37:48 mjr Exp $"; #endif /* configure all options BEFORE including system stuff. */ #include "config.h" #include <stdio.h> #include "multinet_root:[multinet.include.sys]types.h" #include "multinet_root:[multinet.include]netdb.h" #include "multinet_root:[multinet.include.sys]socket.h" #include "multinet_root:[multinet.include.netinet]in.h" #include "multinet_root:[multinet.include.vms]inetiodef.h" #include <ctype.h> #include <varargs.h> #include <ssdef.h> #include <libdtdef.h> #include "mud.h" #include "xact.h" #include "sbuf.h" /* We use event flags 62 and 63 here -- one on a timeout timer, one to synchronize actual network events. We never have more than one event outstanding here. Flags 32, 33, and 34 are used by net_vms.c We use timer reqidt 1, for the hell of it. Since we're cancelling this a lot, you'd best not go using that ID for anything else, eh? */ /* #define XMITVMS_DEBUG */ /* don't bother being too big - this is a TCP */ #define XMBUFSIZ 1024 /* default timeout for I/O or connections */ #define DEFAULT_TIMEOUT 2 /* mud database entry */ typedef struct mudent { int flg; char *name; char *plyport; char *host; char *symhost; char *rempw; char *locpw; struct sockaddr_in addr; int timot; struct mudent *next; } Mudent; /* buffered connection */ typedef struct { int fd; short int iosb[4]; char ibuf[XMBUFSIZ]; char *ibp; int ibc; char obuf[XMBUFSIZ]; char *obp; Mudent *curmp; } Cnxt; static Mudent *getmudent(); static Mudent *mud_list; static Cnxt xbuf; static Mudent *lastmud = (Mudent *)0; /* Look up the remote MUD and set the context up right */ set_remmud(nam) char *nam; { Mudent *mp; if((mp = getmudent(nam)) == (Mudent *)0) return(1); lastmud = xbuf.curmp = mp; return(0); } xc_open(mud) char *mud; { Mudent *mp; long timo[2]; int op; if((mp = getmudent(mud)) == (Mudent *)0) { logf("unknown mud ",mud,"\n",(char *)0); return(-1); } if((xbuf.fd = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("socket"); return(-1); } /* Get a connect to the specified MUD. Time out reasonably fast */ /* Return -1 on error, 0 on success */ /* Set up a timer */ op = LIB$K_DELTA_SECONDS; lib$cvt_to_internal_time(&op,&(mp->timot),timo); sys$setimr(62L,timo,0,1,0); /* Queue up the connect request */ sys$qio(63L,xbuf.fd,IO$_CONNECT,&(xbuf.iosb),0,0, &(mp->addr),sizeof(struct sockaddr_in),0,0,0,0); /* Wait around for something to happen */ sys$wflor(32L,0xC0000000L); /* Top two events flags, 62, 63 */ sys$cantim(1,0); /* Kill timer now, just in case */ /* *what* happened? */ if(xbuf.iosb[0] != SS$_NORMAL){ /* connect didn't work out. Bag. */ sys$cancel(xbuf.fd); return(-1); } /* Connect succeeded, cool. */ #ifdef XMITVMS_DEBUG (void)printf("<<<connected>>>\n"); #endif logf("connection to ",mud,"\n",(char *)0); xbuf.ibp = xbuf.ibuf; xbuf.ibc = 0; xbuf.obp = xbuf.obuf; *xbuf.ibp = *xbuf.obp = '\0'; lastmud = xbuf.curmp = mp; return(0); } xc_initfd(fd) int fd; { xbuf.fd = fd; xbuf.ibp = xbuf.ibuf; xbuf.ibc = 0; xbuf.obp = xbuf.obuf; *xbuf.ibp = *xbuf.obp = '\0'; return(0); } /* Send out an OIF Level 2 greet string to the current mud */ xmit_greet() { /* Firewall. This should NEVER happen. */ if(xbuf.curmp == (Mudent *)0) return(-1); if(xc_write("UnterMUD ",mud_getname()," ",version," " ,(xbuf.curmp)->locpw,"\n",(char *)0)) return(-1); if(xc_flush()) return(-1); return(0); } /* Return 0 if pwd is OK */ check_rempwd(pwd) char *pwd; { /* NEVER happen. */ if(xbuf.curmp == (Mudent *)0) return(1); return(strcmp(pwd,(xbuf.curmp)->rempw)); } /* These grub data out of the LAST Mud contacted. */ char * xc_getips() { extern char *inet_ntoa(); if(lastmud == (Mudent *)0) return(""); return( inet_ntoa(lastmud->addr.sin_addr) ); } char * xc_getmudname() { if(lastmud == (Mudent *)0){ return(""); } return(lastmud->name); } char * xc_gethostname() { if(lastmud == (Mudent *)0) return(""); return(lastmud->symhost); } char * xc_getport() { if(lastmud == (Mudent *)0) return(""); return(lastmud->plyport); } static Mudent * getmudent(mud) char *mud; { Mudent *mp = mud_list; while(mp != (Mudent *)0) { if(!strcmp(mud,mp->name)) return(mp); mp = mp->next; } return((Mudent *)0); } /* define a MUD entry. One semi-sensible thing done here is to pre-resolve the addresses and just stash those. this way we shouldn't have to hit our resolver a whole lot once the MUD is up, if at all. also accept "dot" notation. */ xmit_def_mudent(name,host,symhost,rempw,locpw,port,plyport,timot) char *name; char *host; char *symhost; char *rempw; char *locpw; char *port; char *plyport; char *timot; { Mudent *np; #ifndef NO_HUGE_RESOLVER_CODE struct hostent *hp; #endif struct sockaddr_in tmpa; char *p; p = host; while(*p != '\0' && (*p == '.' || isdigit(*p))) p++; if(*p != '\0') { #ifndef NO_HUGE_RESOLVER_CODE if((hp = gethostbyname(host)) == (struct hostent *)0) { logf("unknown host ",host,"\n",(char *)0); return(1); } (void)bcopy(hp->h_addr,(char *)&tmpa.sin_addr,hp->h_length); #else logf("must use 'dot' notation to define host ",host,"\n",(char *)0); return(1); #endif } else { unsigned long f; if((f = inet_addr(host)) == -1L) return(1); (void)bcopy((char *)&f,(char *)&tmpa.sin_addr,sizeof(f)); } if((np = (Mudent *)malloc(sizeof(Mudent))) == (Mudent *)0) { logf("cannot allocate remote mud map\n",(char *)0); return(1); } (void)bcopy((char *)&tmpa.sin_addr,&(np->addr.sin_addr),sizeof(tmpa.sin_addr)); np->addr.sin_port = htons(atoi(port)); np->addr.sin_family = AF_INET; if(timot != (char *)0) np->timot = atoi(timot); else np->timot = DEFAULT_TIMEOUT; np->name = malloc((unsigned)(strlen(name) + 1)); np->rempw = malloc((unsigned)(strlen(rempw) + 1)); np->locpw = malloc((unsigned)(strlen(locpw) + 1)); np->plyport = malloc((unsigned)(strlen(plyport) + 1)); np->host = malloc((unsigned)(strlen(host) + 1)); np->symhost = malloc((unsigned)(strlen(symhost) + 1)); if(np->name == (char *)0 || np->rempw == (char *)0 || np->locpw == (char *)0 || np->plyport == (char *)0 || np->host == (char *)0 || np->symhost == (char *)0) { logf("cannot allocate remote mud data. owie.\n",(char *)0); return(1); } (void)strcpy(np->name,name); (void)strcpy(np->rempw,rempw); (void)strcpy(np->locpw,locpw); (void)strcpy(np->plyport,plyport); (void)strcpy(np->host,host); (void)strcpy(np->symhost,symhost); np->flg = 0; /* link on */ np->next = mud_list; mud_list = np; return(0); } xc_status() { if(xbuf.fd == -1) return(1); return(0); } xc_close() { shutdown(xbuf.fd,2); close(xbuf.fd); xbuf.fd = -1; xbuf.curmp = (Mudent *)0; logf("hang up connection\n",(char *)0); #ifdef XMITVMS_DEBUG (void)printf("<<<dis-connected>>>\n"); #endif return(0); } char * xc_error() { return("no error"); } /* #### * /* Has to be totally redone. Reads are done with $qio's and timeouts */ xc_sbread(sb) Sbuf *sb; { unsigned long eflags; if(xbuf.fd == -1 || sb == (Sbuf *)0) return(0); sbuf_reset(sb); while(1) { /* buffer empty ? fill. */ if(xbuf.ibc <= 0) { int op,sec; long timo[2]; op = LIB$K_DELTA_SECONDS; if(xbuf.curmp != (Mudent *)0) sec = xbuf.curmp->timot; else sec = DEFAULT_TIMEOUT; /* Start the timer */ lib$cvt_to_internal_time(&op,&sec,timo); sys$setimr(62L,timo,0,1,0); /* Queue up a read */ #ifdef XMITVMS_DEBUG printf("Queuing a read..\n"); #endif xbuf.iosb[0] = xbuf.iosb[1] = 17; sys$qio(63L,xbuf.fd,IO$_READVBLK,&(xbuf.iosb),0,0, xbuf.ibuf,sizeof(xbuf.ibuf),0,0,0,0); /* Wait around for something to happen */ sys$wflor(32L,0xC0000000L); /* Events flags 62 & 63 */ sys$cantim(1,0); /* Kill timer now */ #ifdef XMITVMS_DEBUG sys$readef(35L,&eflags); printf("Something happened! Flags: %x\n",eflags); #endif /* *what* happened? */ if(xbuf.iosb[0] != SS$_NORMAL){ /* read didn't work out. Bag. */ #ifdef XMITVMS_DEBUG printf("Read failed. iosb[0]=%d, iosb[1]=%d\n", xbuf.iosb[0],xbuf.iosb[1]); printf("Buffer contains: %s\n",xbuf.ibuf); socket_perror("hep!"); #endif sys$cancel(xbuf.fd); return(0); } #ifdef XMITVMS_DEBUG printf("Read succeeded, read %d chars\n",xbuf.iosb[1]); #endif xbuf.ibc = xbuf.iosb[1]; if(xbuf.ibc <= 0) return(0); xbuf.ibp = xbuf.ibuf; } /* end of line? */ if(*xbuf.ibp == '\n') { sbuf_put('\0',sb); xbuf.ibp++; xbuf.ibc--; return(1); } /* put. */ sbuf_put(*xbuf.ibp,sb); xbuf.ibp++; xbuf.ibc--; } } xc_flush() { long timo[2]; int op,sec; op = LIB$K_DELTA_SECONDS; if(xbuf.curmp != (Mudent *)0) sec = xbuf.curmp->timot; else sec = DEFAULT_TIMEOUT; /* Start the timer */ lib$cvt_to_internal_time(&op,&sec,timo); sys$setimr(62L,timo,0,1,0); /* Queue up the write request */ sys$qio(63L,xbuf.fd,IO$_WRITEVBLK,&(xbuf.iosb),0,0, xbuf.obuf,xbuf.obp - xbuf.obuf,0,0,0,0); /* Wait around for something to happen */ sys$wflor(32L,0xC0000000L); /* Top two events flags, 62, 63 */ sys$cantim(1,0); /* Kill timer now, just in case */ /* *what* happened? */ if(xbuf.iosb[0] != SS$_NORMAL){ /* write didn't work out. Bag. */ sys$cancel(xbuf.fd); return(1); } else { xbuf.obp = xbuf.obuf; } return(0); } /* VARARGS */ xc_write(va_alist) va_dcl { char *s; va_list ap; #ifdef XMITVMS_DEBUG printf("xc_write: "); #endif va_start(ap); while((s = va_arg(ap,char *)) != (char *)0) { #ifdef XMITVMS_DEBUG printf("%s ",s); #endif while(*s) { if((xbuf.obp - xbuf.obuf) >= sizeof(xbuf.obuf)) if(xc_flush()) return(1); *xbuf.obp++ = *s++; } } va_end(ap); #ifdef XMITVMS_DEBUG printf("\n"); #endif return(0); } /* Maintain a list of MUD-names we've heard about. */ static Mudent *known_muds = 0; static int restrict_known = 0; /* Don't restrict to just known MUDs. */ static Mudent * isknownmud(mud) char *mud; { Mudent *temp, *pos; temp = getmudent(mud); if (temp != NULL) return temp; pos = known_muds; while (pos != NULL) { if (!strcmp(pos->name, mud)) return pos; pos = pos->next; } return (Mudent *) 0; } int xmit_def_knownmud(mud) char *mud; { Mudent *mp; restrict_known = 1; mp = isknownmud(mud); if (mp != 0) return 0; mp = (Mudent *) malloc(sizeof(Mudent)); if (mp == 0) { logf("couldn't alloc memory for knownmud mudent\n", (char *)0); return 1; } mp->name = malloc((unsigned)(strlen(mud) + 1)); if (mp->name == 0) { free(mp); logf("couldn't alloc memory for knownmud name\n", (char *)0); return 1; } (void)strcpy(mp->name, mud); mp->next = known_muds; known_muds = mp; return 0; } /* A given MUD name is okay if: - we don't have MUD security enabled (we have specified no defknownmuds) - it's a MUD we connect to - it's a MUD listed in a _mudconfig defknownmud or - it's us. */ int xmit_okay_remote(name) char *name; { if (!restrict_known) return 1; if (isknownmud(name) != 0) return 1; if (!strcmp(name, mud_getname())) return 1; return 0; }