home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "global.h"
- #include "timer.h"
- #include "mbuf.h"
- #include "netuser.h"
- #include "internet.h"
- #include "tcp.h"
- #include "cmdparse.h"
- #include "misc.h"
- #include "arc.h"
- #include "asy.h"
-
- #include "os.h"
- #include "swis.h"
-
- static int dotcpreset(int, char **);
- static int dohangup(int, char **);
- static int doirtt(int, char **);
- static int dortt(int, char **);
- static int domrtt(int, char **);
- static int dotcpkick(int, char **);
- static int domss(int, char **);
- static int dowindow(int, char **);
- static int dotcpstat(int, char **);
- static int tstat(void);
- static void state_tcp(struct tcb *);
-
- /* TCP connection states */
- char *tcpstates[] = {
- "Closed",
- "Listen",
- "SYN sent",
- "SYN received",
- "Established",
- "FIN wait 1",
- "FIN wait 2",
- "Close wait",
- "Closing",
- "Last ACK",
- "Time wait"
- };
-
- /* TCP closing reasons */
- char *reasons[] = {
- "Normal",
- "Reset",
- "Timeout",
- "ICMP"
- };
-
- static struct timer busy;
- static int busy_checks = 0;
- static int busy_limit = 0;
- static BOOL busy_exit = FALSE;
-
- /* TCP subcommand table */
- struct cmds tcpcmds[] = {
- "hangup", dohangup, 3, "tcp hangup <check> <after> [exit]", NULLCHAR,
- "irtt", doirtt, 1, "tcp irtt <val>", NULLCHAR,
- "kick", dotcpkick, 2, "tcp kick <tcb>", NULLCHAR,
- "mss", domss, 0, "tcp mss <val>", NULLCHAR,
- "mrtt", domrtt, 1, "tcp mrtt <val>", NULLCHAR,
- "reset", dotcpreset, 2, "tcp reset <tcb>", NULLCHAR,
- "rtt", dortt, 3, "tcp rtt <tcb> <val>", NULLCHAR,
- "status", dotcpstat, 0, NULLCHAR, NULLCHAR,
- "window", dowindow, 0, NULLCHAR, NULLCHAR,
- NULLCHAR,
- };
- int dotcp(int argc, char **argv)
- {
- return subcmd(tcpcmds,argc,argv);
- }
-
- /* Eliminate a TCP connection */
- static int dotcpreset(int argc, char **argv)
- {
- register struct tcb *tcb;
- extern char notval[];
-
- argc = argc;
-
- tcb = (struct tcb *)htol(argv[1]);
- if(!tcpval(tcb)){
- cwprintf(NULL, notval);
- return 1;
- }
- close_self(tcb,RESET);
- return 0;
- }
-
- int tcp_hasactive(void)
- {
- register int i;
- register struct tcb *tcb;
-
- for (i = 0; i < NTCB; i++)
- {
- for (tcb = tcbs[i]; tcb != NULLTCB; tcb = tcb->next)
- {
- if (tcb->state > 3 && tcb->state<10)
- return 1;
- }
- }
- return 0;
- }
-
- static void dotcpbusy(void *p)
- {
- p = p;
- start_timer(&busy);
-
- if (tcp_hasactive())
- {
- busy_checks = 0;
- return;
- }
- else
- ++busy_checks;
-
- if (asy_scan())
- cwprintf(NULL, "TCP checks clear = %d Hanging up after %d more\r\n", busy_checks, busy_limit - busy_checks);
- else
- busy_checks = 0;
-
- if (busy_checks == busy_limit)
- {
- iostop();
- if (busy_exit)
- net_exit();
- }
- }
-
- static int dohangup(int argc, char **argv)
- {
- busy.func = dotcpbusy;
- busy.arg = NULL;
- busy_checks = 0;
- busy_limit = atoi(argv[2]);
- cwprintf(NULL, "Check every %s seconds, hangup after %s clear checks\r\n", argv[1], argv[2]);
- if (argc == 4 && strnicmp(argv[3], "exit", MIN(strlen(argv[3]), 4)) == 0)
- {
- busy_exit = TRUE;
- cwprintf(NULL, "and exit program.\r\n");
- }
- if (busy_limit > 0)
- {
- set_timer(&busy, atol(argv[1]) * 1000L);
- start_timer(&busy);
- }
- else
- {
- stop_timer(&busy);
- }
-
- return(0);
- }
-
- /* Set initial round trip time for new connections */
- static int doirtt(int argc, char **argv)
- {
- if(argc < 2)
- cwprintf(NULL, "%lu\r\n",tcp_irtt);
- else
- tcp_irtt = atol(argv[1]);
- return 0;
- }
-
- /* Set maximum round trip time for new connections */
- static int domrtt(int argc, char **argv)
- {
- if(argc < 2)
- cwprintf(NULL, "%lu\r\n",tcp_mrtt*MSPTICK);
- else
- tcp_mrtt = atol(argv[1])/MSPTICK;
- return 0;
- }
-
- /* Set smoothed round trip time for specified TCB */
- static int dortt(int argc, char **argv)
- {
- register struct tcb *tcb;
- extern char notval[];
-
- argc = argc;
-
- tcb = (struct tcb *)htol(argv[1]);
- if(!tcpval(tcb)){
- cwprintf(NULL, notval);
- return 1;
- }
- tcb->srtt = atol(argv[2]);
- return 0;
- }
-
- /* Force a retransmission */
- static int dotcpkick(int argc, char **argv)
- {
- register struct tcb *tcb;
- extern char notval[];
-
- argc = argc;
-
- tcb = (struct tcb *)htol(argv[1]);
- if(kick_tcp(tcb) == -1){
- cwprintf(NULL, notval);
- return 1;
- }
- return 0;
- }
-
- /* Set default maximum segment size */
- static int domss(int argc, char **argv)
- {
- if(argc < 2)
- cwprintf(NULL, "%u\r\n",tcp_mss);
- else
- tcp_mss = atoi(argv[1]);
- return 0;
- }
-
- /* Set default window size */
- static int dowindow(int argc, char **argv)
- {
- if(argc < 2)
- cwprintf(NULL, "%u\r\n",tcp_window);
- else
- tcp_window = atoi(argv[1]);
- return 0;
- }
-
- /* Display status of TCBs */
- static int dotcpstat(int argc, char **argv)
- {
- register struct tcb *tcb;
- extern char notval[];
-
- if(argc < 2){
- tstat();
- } else {
- tcb = (struct tcb *)htol(argv[1]);
- if(tcpval(tcb))
- state_tcp(tcb);
- else
- cwprintf(NULL, notval);
- }
- return 0;
- }
-
- /* Dump TCP stats and summary of all TCBs
- * &TCB Rcv-Q Snd-Q Local socket Remote socket State
- * 1234 0 0 xxx.xxx.xxx.xxx:xxxxx xxx.xxx.xxx.xxx:xxxxx Established
-
- */
- static int tstat(void)
- {
- extern char hostname[];
- register int i;
- register struct tcb *tcb;
-
- cwprintf(NULL, "Local site: %s\n", hostname);
- cwprintf(NULL, "conout %u conin %u reset out %u runt %u chksum err %u bdcsts %u\r\n",
- tcp_stat.conout,tcp_stat.conin,tcp_stat.resets,tcp_stat.runt,
- tcp_stat.checksum,tcp_stat.bdcsts);
- cwprintf(NULL, " &TCB Rcv-Q Snd-Q Local socket Remote socket State\r\n");
- for (i = 0; i < NTCB; i++)
- {
- for (tcb = tcbs[i]; tcb != NULLTCB; tcb = tcb->next)
- {
- cwprintf(NULL, "%8lx%6u%6u ", (long) tcb, tcb->rcvcnt, tcb->sndcnt);
- cwprintf(NULL, "%-15s",tcp_port(tcb->conn.local.port));
- cwprintf(NULL, "%-30s",psocket(&tcb->conn.remote));
- cwprintf(NULL, "%-s",tcpstates[tcb->state]);
- if (tcb->state == LISTEN && (tcb->flags & CLONE))
- cwprintf(NULL, " (S)");
- cwprintf(NULL, "\r\n");
- }
- }
- return(0);
- }
- /*
- static int tstat(void)
- {
- register int i;
- register struct tcb *tcb;
-
- cwprintf(NULL, "conout %u conin %u reset out %u runt %u chksum err %u bdcsts %u\r\n",
- tcp_stat.conout,tcp_stat.conin,tcp_stat.resets,tcp_stat.runt,
- tcp_stat.checksum,tcp_stat.bdcsts);
- cwprintf(NULL, " &TCB Rcv-Q Snd-Q Local socket Remote socket State\r\n");
- for(i=0;i<NTCB;i++){
- for(tcb=tcbs[i];tcb != NULLTCB;tcb = tcb->next){
- cwprintf(NULL, "%6lx%6u%6u ",(long)tcb,tcb->rcvcnt,tcb->sndcnt);
- cwprintf(NULL, "%-24s",psocket(&tcb->conn.local));
- cwprintf(NULL, "%-24s",psocket(&tcb->conn.remote));
- cwprintf(NULL, "%-s",tcpstates[tcb->state]);
- if(tcb->state == LISTEN && (tcb->flags & CLONE))
- cwprintf(NULL, " (S)");
- cwprintf(NULL, "\r\n");
- }
- }
- return 0;
- }
- */
- /* Dump a TCP control block in detail */
- static void state_tcp(struct tcb *tcb)
- {
- int32 sent,recvd;
-
- if(tcb == NULLTCB)
- return;
- /* Compute total data sent and received; take out SYN and FIN */
- sent = tcb->snd.una - tcb->iss; /* Acknowledged data only */
- recvd = tcb->rcv.nxt - tcb->irs;
- switch(tcb->state){
- case LISTEN:
- case SYN_SENT: /* Nothing received or acked yet */
- sent = recvd = 0;
- break;
- case SYN_RECEIVED:
- recvd--; /* Got SYN, no data acked yet */
- sent = 0;
- break;
- case ESTABLISHED: /* Got and sent SYN */
- case FINWAIT1: /* FIN not acked yet */
- sent--;
- recvd--;
- break;
- case FINWAIT2: /* Our SYN and FIN both acked */
- sent -= 2;
- recvd--;
- break;
- case CLOSE_WAIT: /* Got SYN and FIN, our FIN not yet acked */
- case CLOSING:
- case LAST_ACK:
- sent--;
- recvd -= 2;
- break;
- case TIME_WAIT: /* Sent and received SYN/FIN, all acked */
- sent -= 2;
- recvd -= 2;
- break;
- }
- cwprintf(NULL, "Local: %s",psocket(&tcb->conn.local));
- cwprintf(NULL, " Remote: %s",psocket(&tcb->conn.remote));
- cwprintf(NULL, " State: %s\r\n",tcpstates[tcb->state]);
- cwprintf(NULL, " Init seq Unack Next Resent CWind Thrsh Wind MSS Queue Total\r\n");
- cwprintf(NULL, "Send:");
- cwprintf(NULL, "%9lx",tcb->iss);
- cwprintf(NULL, "%9lx",tcb->snd.una);
- cwprintf(NULL, "%9lx",tcb->snd.nxt);
- cwprintf(NULL, "%7lu",tcb->resent);
- cwprintf(NULL, "%6u",tcb->cwind);
- cwprintf(NULL, "%6u",tcb->ssthresh);
- cwprintf(NULL, "%6u",tcb->snd.wnd);
- cwprintf(NULL, "%5u",tcb->mss);
- cwprintf(NULL, "%6u",tcb->sndcnt);
- cwprintf(NULL, "%11lu\r\n",sent);
-
- cwprintf(NULL, "Recv:");
- cwprintf(NULL, "%9lx",tcb->irs);
- cwprintf(NULL, " ");
- cwprintf(NULL, "%9lx",tcb->rcv.nxt);
- cwprintf(NULL, "%7lu",tcb->rerecv);
- cwprintf(NULL, " ");
- cwprintf(NULL, " ");
- cwprintf(NULL, "%6u",tcb->rcv.wnd);
- cwprintf(NULL, " ");
- cwprintf(NULL, "%6u",tcb->rcvcnt);
- cwprintf(NULL, "%11lu\r\n",recvd);
-
- if(tcb->reseq != (struct reseq *)NULL){
- register struct reseq *rp;
-
- cwprintf(NULL, "Reassembly queue:\r\n");
- for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
- cwprintf(NULL, " seq x%lx %u bytes\r\n",rp->seg.seq,rp->length);
- }
- }
- if(tcb->backoff > 0)
- cwprintf(NULL, "Backoff %u ",tcb->backoff);
- if(tcb->flags & RETRAN)
- cwprintf(NULL, "Retrying ");
- switch(tcb->timer.state){
- case TIMER_STOP:
- cwprintf(NULL, "Timer stopped ");
- break;
- case TIMER_RUN:
- cwprintf(NULL, "Timer running (%ld/%ld ms) ",
- (long)MSPTICK * (tcb->timer.start - tcb->timer.count),
- (long)MSPTICK * tcb->timer.start);
- break;
- case TIMER_EXPIRE:
- cwprintf(NULL, "Timer expired ");
- }
- cwprintf(NULL, "SRTT %ld ms Mean dev %ld ms\r\n",tcb->srtt,tcb->mdev);
- }
-
- int rem_kick(void)
- {
- register int i;
- register struct tcb *tcb;
- for(i=0;i<NTCB;i++){
- for(tcb=tcbs[i];tcb != NULLTCB;tcb = tcb->next){
- kick_tcp(tcb);
- }
- }
- return 0;
- }
-