/* * Amiga version changes are * * Copyright (c)1987 * Louis A. Mamakos * * For non-commercial use only. */ /* Main network program - provides both client and server functions */ #define NSESSIONS 10 /* Maximum interactive client sessions */ #define HOSTNAMELEN 32 /* changed from 16 by Bdale 860812 */ #ifndef STARTUP #ifdef AMIGA #define STARTUP "s:net-sequence" #else #define STARTUP "/autoexec.net" /* File to read startup commands from */ #endif #endif #include #include "machdep.h" #include "mbuf.h" #include "netuser.h" #include "timer.h" #include "icmp.h" #include "iface.h" #include "ip.h" #include "tcp.h" #include "ftp.h" #include "telnet.h" #include "session.h" #include "cmdparse.h" #ifdef AMIGA #include "amiga.h" #else #include "pc.h" #endif extern struct interface *ifaces; struct session sessions[NSESSIONS]; struct session *current; extern char major_rev[], minor_rev[]; int mode; FILE *logfp; #ifdef TRACE #include "trace.h" int32 trace; #endif char hostname[HOSTNAMELEN]; int32 aton(); int16 lport = 1001; #ifdef AMIGA char prompt[] = "\33[1;33mnet>\33[m "; /* make it standout and stuff */ #else char prompt[] = "net> "; #endif char nospace[] = "No space!!\r\n"; /* Generic malloc fail message */ static char notval[] = "Not a valid TCB\r\n"; #ifndef MSDOS /* PC uses F-10 key always */ static char escape = 0x1d; /* default escape character is ^] */ #endif /* Command lookup and branch table */ int go(),cmdmode(),dodigipeat(), doipaddr(),dotelnet(),doexit(),doclose(),dohostname(), doreset(),dotcpstat(),dotrace(),doescape(),dospeed(),dohelp(), dowindow(),doroute(),doecho(), dolog(),doipstat(),doicmpstat(),doetherstat(),memstat(),doarp(), dosession(),doftp(),domss(),dostart(),dostop(),doattach(), domycall(),dosmtptick(),doudpstat(),dottl(),dokiss(),dotcpkick(), doeol(); #ifdef HAPN int dohapnstat(); #endif HAPN #ifdef AMIGADEVDRV int DriverInit(), DriverShutdown(), CheckTcp(); #endif static struct cmds cmds[] = { /* The "go" command must be first */ "", go, 0, NULLCHAR, NULLCHAR, "arp", doarp, 0, NULLCHAR, NULLCHAR, "attach", doattach, 2, "attach ", NULLCHAR, "close", doclose, 0, NULLCHAR, NULLCHAR, #ifdef AX25 "digipeat", dodigipeat, 0, NULLCHAR, NULLCHAR, #endif #ifdef AMIGADEVDRV "checktcp", CheckTcp, 0, NULLCHAR, NULLCHAR, "driver", DriverInit, 0, NULLCHAR, NULLCHAR, "driveroff", DriverShutdown, 0, NULLCHAR, NULLCHAR, #endif "echo", doecho, 0, NULLCHAR, NULLCHAR, "eol", doeol, 0, NULLCHAR, "eol options: unix, standard", #ifndef MSDOS "escape", doescape, 0, NULLCHAR, NULLCHAR, #endif #ifdef PC_EC "etherstat", doetherstat, 0, NULLCHAR, NULLCHAR, #endif PC_EC "exit", doexit, 0, NULLCHAR, NULLCHAR, "ftp", doftp, 2, "ftp
", NULLCHAR, #ifdef HAPN "hapnstat", dohapnstat, 0, NULLCHAR, NULLCHAR, #endif HAPN "help", dohelp, 0, NULLCHAR, NULLCHAR, "hostname", dohostname, 0, NULLCHAR, NULLCHAR, "log", dolog, 0, NULLCHAR, NULLCHAR, "icmpstat", doicmpstat, 0, NULLCHAR, NULLCHAR, "ipaddr", doipaddr, 0, NULLCHAR, NULLCHAR, "ipstat", doipstat, 0, NULLCHAR, NULLCHAR, #ifdef AX25 "kiss", dokiss, 0, NULLCHAR, NULLCHAR, #endif "smtp", dosmtptick, 0, NULLCHAR, NULLCHAR, #ifndef AMIGA "memstat", memstat, 0, NULLCHAR, NULLCHAR, #endif "mss", domss, 0, NULLCHAR, NULLCHAR, #ifdef AX25 "mycall", domycall, 0, NULLCHAR, NULLCHAR, #endif "reset", doreset, 0, NULLCHAR, NULLCHAR, "route", doroute, 0, NULLCHAR, NULLCHAR, "session", dosession, 0, NULLCHAR, NULLCHAR, "speed", dospeed, 0, NULLCHAR, NULLCHAR, #ifdef SERVERS "start", dostart, 2, "start ",NULLCHAR, "stop", dostop, 2, "stop ", NULLCHAR, #endif "tcpstat", dotcpstat, 0, NULLCHAR, NULLCHAR, "tcpkick", dotcpkick, 0, NULLCHAR, NULLCHAR, "telnet", dotelnet, 2, "telnet
", NULLCHAR, "trace", dotrace, 0, NULLCHAR, NULLCHAR, "ttl", dottl, 0, NULLCHAR, NULLCHAR, "udpstat", doudpstat, 0, NULLCHAR, NULLCHAR, "window", dowindow, 0, NULLCHAR, NULLCHAR, "?", dohelp, 0, NULLCHAR, NULLCHAR, NULLCHAR, NULLFP, 0, "Unknown command; type \"?\" for list", NULLCHAR, }; /* "route" subcommands */ int doadd(),dodrop(); static struct cmds rtcmds[] = { "add", doadd, 3, "route add [/] [gateway] [metric]", "Add failed", "drop", dodrop, 2, "route drop [/]", "Not in table", NULLCHAR, NULLFP, 0, "route subcommands: add, drop", NULLCHAR, }; #ifdef SERVERS /* "start" and "stop" subcommands */ int ftp_start(),smtp_start(),discard_start(),echo_start(),telnet_start(); static struct cmds startcmds[] = { "discard", discard_start, 0, NULLCHAR, NULLCHAR, "echo", echo_start, 0, NULLCHAR, NULLCHAR, "ftp", ftp_start, 0, NULLCHAR, NULLCHAR, "smtp", smtp_start, 0, NULLCHAR, NULLCHAR, "telnet", telnet_start, 0, NULLCHAR, NULLCHAR, NULLCHAR, NULLFP, 0, "start options: discard, echo, ftp, smtp, telnet", NULLCHAR, }; int ftp_stop(),smtp_stop(),echo_stop(),discard_stop(),telnet_stop(); static struct cmds stopcmds[] = { "discard", discard_stop, 0, NULLCHAR, NULLCHAR, "echo", echo_stop, 0, NULLCHAR, NULLCHAR, "ftp", ftp_stop, 0, NULLCHAR, NULLCHAR, "smtp", smtp_stop, 0, NULLCHAR, NULLCHAR, "telnet", telnet_stop, 0, NULLCHAR, NULLCHAR, NULLCHAR, NULLFP, 0, "stop options: discard, echo, ftp, smtp, telnet", NULLCHAR, }; #endif main(argc,argv) int argc; char *argv[]; { static char inbuf[BUFSIZ]; /* keep it off the stack */ int c; char *ttybuf,*fgets(); int16 cnt; int ttydriv(); int cmdparse(); void check_time(); FILE *fp; struct interface *ifp; #ifdef AMIGA char *startup = STARTUP; #endif ioinit(); printf("KA9Q Internet Protocol Package, v%s.%s\n",major_rev,minor_rev); #ifdef AMIGA if (argc > 1) startup = argv[1]; if((fp = fopen(startup,"r")) != NULLFILE){ while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){ printf(prompt); printf(inbuf); cmdparse(cmds, inbuf); } fclose(fp); } else printf("Can't read inital commands from %s\n", startup); #else if((fp = fopen(STARTUP,"r")) != NULLFILE){ while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){ cmdparse(cmds,inbuf); } fclose(fp); } #endif cmdmode(); smtpclinit(); /* arm SMTP background client timer */ /* Main commutator loop */ for(;;){ /* Process any keyboard input */ while((c = kbread()) != -1){ #ifdef MSDOS /* c == -2 means the command escape key (F10) */ if(c == -2){ if(mode != CMD_MODE){ printf("\r\n"); cmdmode(); } continue; } #else if(c == escape && escape != 0 && mode != CMD_MODE) { printf("\r\n"); cmdmode(); continue; } #endif if((cnt = ttydriv(c,&ttybuf)) == 0) continue; switch(mode){ case CMD_MODE: (void)cmdparse(cmds,ttybuf); fflush(stdout); break; case CONV_MODE: #ifndef MSDOS if(ttybuf[0] == escape && escape != 0){ printf("\r\n"); cmdmode(); } else #endif MSDOS if(current->parse != NULLFP) (*current->parse)(ttybuf,cnt); break; } if(mode == CMD_MODE){ printf(prompt); fflush(stdout); } } /* Service the interfaces */ for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next){ if(ifp->recv != NULLFP) (*ifp->recv)(ifp); } /* Service the clock if it has ticked */ check_time(); #ifdef AMIGADEVDRV /* check device driver open request */ check_driver(); CheckTcp(); #else #ifdef MSDOS /* Tell DoubleDos to let the other task run for awhile. * If DoubleDos isn't active, this is a no-op */ giveup(); #else /* Wait until interrupt, then do it all over again */ eihalt(); #endif #endif AMIGADEVDRV } } /* Enter command mode */ int cmdmode() { if(mode != CMD_MODE){ mode = CMD_MODE; cooked(); printf(prompt); fflush(stdout); } return 0; } /* Select and display sessions */ static dosession(argc,argv) int argc; char *argv[]; { unsigned i; struct session *s; extern char *tcpstates[]; char *psocket(); if(argc < 2){ printf(" # Type Remote socket TCB State\r\n"); for(s=sessions;s < & sessions[NSESSIONS];s++){ switch(s->type){ case TELNET: #ifndef AMIGA printf("%c%-3d%Telnet %-23s%4x %-s\r\n", (current == s)? '*':' ', s - sessions, psocket(&s->cb.telnet->tcb->conn.remote), (int)s->cb.telnet->tcb, tcpstates[s->cb.telnet->tcb->state]); #else printf("%c%-3d%Telnet %-23s%6lx %-s\r\n", (current == s)? '*':' ', s - sessions, psocket(&s->cb.telnet->tcb->conn.remote), (unsigned long)s->cb.telnet->tcb, tcpstates[s->cb.telnet->tcb->state]); #endif break; case FTP: #ifndef AMIGA printf("%c%-3d%FTP %-23s%4x %-s\r\n", (current == s)? '*':' ', s - sessions, psocket(&s->cb.ftp->control->conn.remote), (int)s->cb.ftp->control, tcpstates[s->cb.ftp->control->state]); #else printf("%c%-3d%FTP %-23s%6lx %-s\r\n", (current == s)? '*':' ', s - sessions, psocket(&s->cb.ftp->control->conn.remote), (unsigned long)s->cb.ftp->control, tcpstates[s->cb.ftp->control->state]); #endif break; } } return 0; } i = atoi(argv[1]); if(i > NSESSIONS){ printf("Invalid session: %d\r\n",i); return 1; } if(sessions[i].type == FREE){ printf("Inactive session: %d\r\n",i); return 1; } current = &sessions[i]; go(); return 0; } /* Enter conversational mode with current session */ int go() { void rcv_char(),r_ctl(); if(current == NULLSESSION || current->type == FREE) return 0; mode = CONV_MODE; switch(current->type){ case TELNET: if(current->cb.telnet->remote[TN_ECHO]) raw(); /* Re-establish raw mode if it was set */ rcv_char(current->cb.telnet->tcb,0); /* Get any pending input */ break; case FTP: r_ctl(current->cb.ftp->control,0); break; } return 0; } #ifdef AX25 extern int digipeat; dodigipeat(argc,argv) int argc; char *argv[]; { if(argc == 1) { printf("digipeat %s\r\n",digipeat ? "on" : "off"); } else { if(strcmp(argv[1],"on") == 0) digipeat = 1; else digipeat = 0; } } #endif static doipaddr(argc,argv) int argc; char *argv[]; { char *inet_ntoa(); if(argc < 2) printf("%s\r\n",inet_ntoa(ip_addr)); else ip_addr = aton(argv[1]); return 0; } static doexit(argc,argv) int argc; char *argv[]; { iostop(); DriverShutdown(); exit(0); } static doclose(argc,argv) int argc; char *argv[]; { if(current == NULLSESSION){ printf("No current session\r\n"); return 0; } switch(current->type){ case TELNET: close_tcp(current->cb.telnet->tcb); break; case FTP: close_tcp(current->cb.ftp->control); break; } return 0; } static doreset(argc,argv) int argc; char *argv[]; { long htol(); struct tcb *tcb; if(argc < 2){ if(current == NULLSESSION){ printf("No current session\r\n"); return 1; } switch(current->type){ case TELNET: tcb = current->cb.telnet->tcb; break; case FTP: tcb = current->cb.ftp->control; break; } } else tcb = (struct tcb *)htol(argv[1]); if(!tcpval(tcb)){ printf(notval); return 1; } close_self(tcb,RESET); return 0; } static int dotcpstat(argc,argv) int argc; char *argv[]; { long htol(); register struct tcb *tcb; if(argc < 2){ tcpstat(); } else { tcb = (struct tcb *)htol(argv[1]); if(tcpval(tcb)) state_tcp(tcb); else printf(notval); } return 0; } static int dotcpkick(argc,argv) int argc; char *argv[]; { long htol(); register struct tcb *tcb; void tcp_timeout(); if(argc < 2){ if(current == NULLSESSION){ printf("No current session\r\n"); return 1; } switch(current->type){ case TELNET: tcb = current->cb.telnet->tcb; break; case FTP: tcb = current->cb.ftp->control; break; } } else tcb = (struct tcb *)htol(argv[1]); if(!tcpval(tcb)){ printf(notval); return 1; } if(argc > 2){ /* Optional value for SRTT */ tcb->srtt = atoi(argv[2]); } /* Don't actually do anything unless something is pending */ if(tcb->sndcnt != 0){ tcb->retry = 0; tcp_timeout((int *)tcb); } return 0; } static int dotrace(argc,argv) int argc; char *argv[]; { long htol(); #ifdef TRACE if(argc < 2) printf("trace level 0x%08lx\r\n",trace); else trace = htol(argv[1]); return 0; #else printf("Trace not enabled - recompile with TRACE defined\r\n"); #endif } static dohostname(argc,argv) int argc; char *argv[]; { char *strncpy(); if(argc < 2) printf("%s\r\n",hostname); else strncpy(hostname,argv[1],HOSTNAMELEN); return 0; } static int dolog(argc,argv) int argc; char *argv[]; { char *strncpy(); #ifdef AMIGA static char logname[45]; /* long enough for CON:10/10/300/300/title */ #else static char logname[15]; #endif if(argc < 2){ if(logfp) printf("Logging to %s\r\n",logname); else printf("Logging off\r\n"); return 0; } if(logfp){ fclose(logfp); logfp = NULLFILE; } if(strcmp(argv[1],"stop") != 0){ #ifdef AMIGA strncpy(logname,argv[1],45); #else strncpy(logname,argv[1],15); #endif logfp = fopen(logname,"a+"); } return 0; } #ifndef MSDOS static int doescape(argc,argv) int argc; char *argv[]; { if(argc < 2) printf("0x%x\r\n",escape); else escape = *argv[1]; return 0; } #endif MSDOS static int dohelp(argc,argv) int argc; char *argv[]; { register struct cmds *cmdp; int i,j; printf("Main commands:\r\n"); for(i=0,cmdp = cmds;cmdp->name != NULL;cmdp++,i++){ printf("%s",cmdp->name); if((i % 4) == 3) printf("\r\n"); else { for(j=strlen(cmdp->name);j < 16; j++) putchar(' '); } } if((i % 4) != 0) printf("\r\n"); return 0; } static int domss(argc,argv) int argc; char *argv[]; { if(argc < 2) printf("%d\r\n",tcp_mss); else tcp_mss = atoi(argv[1]); return 0; } static int dowindow(argc,argv) int argc; char *argv[]; { if(argc < 2) printf("%d\r\n",tcp_window); else tcp_window = atoi(argv[1]); return 0; } static int dottl(argc,argv) char *argv[]; { if(argc < 2) printf("%u\r\n",ip_ttl & 0xff); else ip_ttl = atoi(argv[1]); return 0; } struct session * newsession() { register int i; for(i=0;itype = FREE; } /* Display and/or manipulate routing table */ int doroute(argc,argv) int argc; char *argv[]; { if(argc < 2){ dumproute(); return 0; } return subcmd(rtcmds,argc,argv); } /* Add an entry to the routing table * E.g., "add 1.2.3.4 ax0 5.6.7.8 3" */ int doadd(argc,argv) int argc; char *argv[]; { struct interface *ifp; int32 dest,gateway; unsigned bits; char *bitp,*index(); int metric; if(strcmp(argv[1],"default") == 0){ dest = 0; bits = 0; } else { dest = aton(argv[1]); /* If IP address is followed by an optional slash and * a length field, (e.g., 128.96/16) get it; * otherwise assume a full 32-bit address */ if((bitp = index(argv[1],'/')) != NULLCHAR){ bitp++; bits = atoi(bitp); } else bits = 32; } for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){ if(strcmp(argv[2],ifp->name) == 0) break; } if(ifp == NULL){ printf("Interface \"%s\" unknown\r\n",argv[2]); return 1; } if(argc > 3) gateway = aton(argv[3]); else gateway = 0; if(argc > 4) metric = atoi(argv[4]); else metric = 0; rt_add(dest,bits,gateway,metric,ifp); return 0; } /* Drop an entry from the routing table * E.g., "drop 128.96/16 */ int dodrop(argc,argv) int argc; char *argv[]; { char *bitp,*index(); unsigned bits; /* If IP address is followed by an optional slash and length field, * (e.g., 128.96/16) get it; otherwise assume a full 32-bit address */ if((bitp = index(argv[1],'/')) != NULLCHAR){ bitp++; bits = atoi(bitp); } else bits = 32; return rt_drop(aton(argv[1]),bits); } #ifdef SERVERS dostart(argc,argv) int argc; char *argv[]; { return subcmd(startcmds,argc,argv); } dostop(argc,argv) int argc; char *argv[]; { return subcmd(stopcmds,argc,argv); } #endif SERVERS doecho(argc,argv) int argc; char *argv[]; { extern int refuse_echo; if(argc < 2){ if(refuse_echo) printf("Refuse\r\n"); else printf("Accept\r\n"); } else { if(strcmp(argv[1],"refuse") == 0) refuse_echo = 1; else if(strcmp(argv[1],"accept") == 0) refuse_echo = 0; else return -1; } return 0; } /* set for unix end of line for remote echo mode telnet */ doeol(argc,argv) int argc; char *argv[]; { extern int unix_line_mode; if(argc < 2){ if(unix_line_mode) printf("Unix\r\n"); else printf("Standard\r\n"); } else { if(strcmp(argv[1],"unix") == 0) unix_line_mode = 1; else if(strcmp(argv[1],"standard") == 0) unix_line_mode = 0; else { return -1; } } return 0; } /* List of supported hardware devices */ #ifdef PC_EC int ec_attach(); #endif int asy_attach(); #ifdef PC100 int pc_attach(); #endif #ifdef HAPN int hapn_attach(); #endif #ifdef NETROM int netrom_attach(); #endif struct cmds attab[] = { #ifdef NETROM /* NET/ROM virtual interface using companion asy interface in AX.25 mode */ "netrom", netrom_attach, 4, "attach netrom ax25