tcpcmd.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:8k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* TCP control and status routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "cmdparse.h"
  12. #include "commands.h"
  13. #include "socket.h"
  14. #include "session.h"
  15. int Tcp_tstamps = 1;
  16. static int doirtt(int argc,char *argv[],void *p);
  17. static int domss(int argc,char *argv[],void *p);
  18. static int dortt(int argc,char *argv[],void *p);
  19. static int dotcpkick(int argc,char *argv[],void *p);
  20. static int dotcpreset(int argc,char *argv[],void *p);
  21. static int dotcpstat(int argc,char *argv[],void *p);
  22. static int dotcptr(int argc,char *argv[],void *p);
  23. static int dowindow(int argc,char *argv[],void *p);
  24. static int dosyndata(int argc,char *argv[],void *p);
  25. static int dotimestamps(int argc,char *argv[],void *p);
  26. static int tstat(void);
  27. static int keychar(int c);
  28. static void tcprepstat(int interval,void *p1,void *p2);
  29. /* TCP subcommand table */
  30. static struct cmds Tcpcmds[] = {
  31. "irtt", doirtt, 0, 0, NULL,
  32. "kick", dotcpkick, 0, 2, "tcp kick <tcb>",
  33. "mss", domss, 0, 0, NULL,
  34. "reset", dotcpreset, 0, 2, "tcp reset <tcb>",
  35. "rtt", dortt, 0, 3, "tcp rtt <tcb> <val>",
  36. "status", dotcpstat, 0, 0, "tcp stat <tcb> [<interval>]",
  37. "syndata", dosyndata, 0, 0, NULL,
  38. "timestamps", dotimestamps, 0, 0,   NULL,
  39. "trace", dotcptr, 0, 0, NULL,
  40. "window", dowindow, 0, 0, NULL,
  41. NULL,
  42. };
  43. int
  44. dotcp(argc,argv,p)
  45. int argc;
  46. char *argv[];
  47. void *p;
  48. {
  49. return subcmd(Tcpcmds,argc,argv,p);
  50. }
  51. static int
  52. dotcptr(argc,argv,p)
  53. int argc;
  54. char *argv[];
  55. void *p;
  56. {
  57. return setbool(&Tcp_trace,"TCP state tracing",argc,argv);
  58. }
  59. static int
  60. dotimestamps(argc,argv,p)
  61. int argc;
  62. char *argv[];
  63. void *p;
  64. {
  65. return setbool(&Tcp_tstamps,"TCP timestamps",argc,argv);
  66. }
  67. /* Eliminate a TCP connection */
  68. static int
  69. dotcpreset(argc,argv,p)
  70. int argc;
  71. char *argv[];
  72. void *p;
  73. {
  74. register struct tcb *tcb;
  75. tcb = (struct tcb *)ltop(htol(argv[1]));
  76. if(!tcpval(tcb)){
  77. printf(Notval);
  78. return 1;
  79. }
  80. reset_tcp(tcb);
  81. return 0;
  82. }
  83. /* Set initial round trip time for new connections */
  84. static int
  85. doirtt(argc,argv,p)
  86. int argc;
  87. char *argv[];
  88. void *p;
  89. {
  90. struct tcp_rtt *tp;
  91. setlong(&Tcp_irtt,"TCP default irtt",argc,argv);
  92. if(argc < 2){
  93. for(tp = &Tcp_rtt[0];tp < &Tcp_rtt[RTTCACHE];tp++){
  94. if(tp->addr != 0){
  95. printf("%s: srtt %lu mdev %lun",
  96.  inet_ntoa(tp->addr),
  97.  tp->srtt,tp->mdev);
  98. }
  99. }
  100. }
  101. return 0;
  102. }
  103. /* Set smoothed round trip time for specified TCB */
  104. static int
  105. dortt(argc,argv,p)
  106. int argc;
  107. char *argv[];
  108. void *p;
  109. {
  110. register struct tcb *tcb;
  111. tcb = (struct tcb *)ltop(htol(argv[1]));
  112. if(!tcpval(tcb)){
  113. printf(Notval);
  114. return 1;
  115. }
  116. tcb->srtt = atol(argv[2]);
  117. return 0;
  118. }
  119. /* Force a retransmission */
  120. static int
  121. dotcpkick(argc,argv,p)
  122. int argc;
  123. char *argv[];
  124. void *p;
  125. {
  126. register struct tcb *tcb;
  127. tcb = (struct tcb *)ltop(htol(argv[1]));
  128. if(kick_tcp(tcb) == -1){
  129. printf(Notval);
  130. return 1;
  131. }
  132. return 0;
  133. }
  134. /* Set default maximum segment size */
  135. static int
  136. domss(argc,argv,p)
  137. int argc;
  138. char *argv[];
  139. void *p;
  140. {
  141. return setshort(&Tcp_mss,"TCP MSS",argc,argv);
  142. }
  143. /* Set default window size */
  144. static int
  145. dowindow(argc,argv,p)
  146. int argc;
  147. char *argv[];
  148. void *p;
  149. {
  150. return setshort(&Tcp_window,"TCP window",argc,argv);
  151. }
  152. static int
  153. dosyndata(argc,argv,p)
  154. int argc;
  155. char *argv[];
  156. void *p;
  157. {
  158. return setbool(&Tcp_syndata,"TCP syn+data piggybacking",argc,argv);
  159. }
  160. /* Display status of TCBs */
  161. static int
  162. dotcpstat(argc,argv,p)
  163. int argc;
  164. char *argv[];
  165. void *p;
  166. {
  167. register struct tcb *tcb;
  168. int32 interval = 0;
  169. if(argc < 2){
  170. tstat();
  171. return 0;
  172. }
  173. if(argc > 2)
  174. interval = atol(argv[2]);
  175. tcb = (struct tcb *)ltop(htol(argv[1]));
  176. if(!tcpval(tcb)){
  177. printf(Notval);
  178. return 1;
  179. }
  180. if(interval == 0){
  181. st_tcp(tcb);
  182. return 0;
  183. }
  184. newproc("rep tcp stat",512,tcprepstat,interval,(void *)tcb,NULL,0);
  185. return 0;
  186. }
  187. static void
  188. tcprepstat(interval,p1,p2)
  189. int interval;
  190. void *p1;
  191. void *p2;
  192. {
  193. struct tcb *tcb = (struct tcb *)p1;
  194. struct session *sp;
  195. if((sp = newsession(Cmdline,REPEAT,1)) == NULL){
  196. printf("Too many sessionsn");
  197. return;
  198. }
  199. sp->inproc = keychar; /* Intercept ^C */
  200. while(sp->inproc == keychar){ /* ^C will clear sp->inproc */
  201. printf("%c[2J",ESC); /* Clear screen */
  202. st_tcp(tcb);
  203. if(tcb->state == TCP_CLOSED || ppause(interval) == -1)
  204. break;
  205. }
  206. keywait(NULL,1);
  207. freesession(sp);
  208. }
  209. /* Dump TCP stats and summary of all TCBs
  210. /*     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  211.  *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  212.  */
  213. static int
  214. tstat()
  215. {
  216. register int i;
  217. register struct tcb *tcb;
  218. int j;
  219. for(j=i=1;i<=NUMTCPMIB;i++){
  220. if(Tcp_mib[i].name == NULL)
  221. continue;
  222. printf("(%2u)%-20s%10lu",i,Tcp_mib[i].name,
  223.  Tcp_mib[i].value.integer);
  224. if(j++ % 2)
  225. printf("     ");
  226. else
  227. printf("n");
  228. }
  229. if((j % 2) == 0)
  230. printf("n");
  231. printf("&TCB      Rcv-Q Snd-Q  Local socket           Remote socket          Staten");
  232. for(tcb=Tcbs;tcb != NULL;tcb = tcb->next){
  233. printf("%9p%6u%6u  ",tcb,tcb->rcvcnt,tcb->sndcnt);
  234. printf("%-23s",pinet(&tcb->conn.local));
  235. printf("%-23s",pinet(&tcb->conn.remote));
  236. printf("%-s",Tcpstates[tcb->state]);
  237. if(tcb->state == TCP_LISTEN && tcb->flags.clone)
  238. printf(" (S)");
  239. printf("n");
  240. }
  241. return 0;
  242. }
  243. /* Dump a TCP control block in detail */
  244. void
  245. st_tcp(tcb)
  246. struct tcb *tcb;
  247. {
  248. int32 sent,recvd;
  249. if(tcb == NULL)
  250. return;
  251. /* Compute total data sent and received; take out SYN and FIN */
  252. sent = tcb->snd.una - tcb->iss; /* Acknowledged data only */
  253. recvd = tcb->rcv.nxt - tcb->irs;
  254. switch(tcb->state){
  255. case TCP_LISTEN:
  256. case TCP_SYN_SENT: /* Nothing received or acked yet */
  257. sent = recvd = 0;
  258. break;
  259. case TCP_SYN_RECEIVED:
  260. recvd--; /* Got SYN, no data acked yet */
  261. sent = 0;
  262. break;
  263. case TCP_ESTABLISHED: /* Got and sent SYN */
  264. case TCP_FINWAIT1: /* FIN not acked yet */
  265. sent--;
  266. recvd--;
  267. break;
  268. case TCP_FINWAIT2: /* Our SYN and FIN both acked */
  269. sent -= 2;
  270. recvd--;
  271. break;
  272. case TCP_CLOSE_WAIT: /* Got SYN and FIN, our FIN not yet acked */
  273. case TCP_CLOSING:
  274. case TCP_LAST_ACK:
  275. sent--;
  276. recvd -= 2;
  277. break;
  278. case TCP_TIME_WAIT: /* Sent and received SYN/FIN, all acked */
  279. sent -= 2;
  280. recvd -= 2;
  281. break;
  282. }
  283. printf("Local: %s",pinet(&tcb->conn.local));
  284. printf(" Remote: %s",pinet(&tcb->conn.remote));
  285. printf(" State: %sn",Tcpstates[tcb->state]);
  286. printf("         Unack     Next Resent CWind Thrsh  Wind  MSS Queue  Thruput      Totaln");
  287. printf("Send: %08lx %08lx%7lu%6lu%6lu%6lu%5lu%6lu%9lu%11lun",
  288.  tcb->snd.una,tcb->snd.nxt,tcb->resent,tcb->cwind,tcb->ssthresh,
  289.  tcb->snd.wnd,tcb->mss,tcb->sndcnt,tcb->txbw,sent);
  290. printf("Recv:          %08lx%7lu            %6lu     %6lu%9lu%11lun",
  291.  tcb->rcv.nxt,tcb->rerecv,tcb->rcv.wnd,tcb->rcvcnt,tcb->rxbw,recvd);
  292. printf("Dup acks   Backoff   Timeouts   Source Quench   Unreachables   Powern");
  293. printf("%8u%10u%11lu%16lu%15lu",tcb->dupacks,tcb->backoff,tcb->timeouts,
  294.  tcb->quench,tcb->unreach);
  295. if(tcb->srtt != 0)
  296. printf("%8lu",1000*tcb->txbw/tcb->srtt);
  297. else
  298. printf("     INF");
  299. if(tcb->flags.retran)
  300. printf(" Retry");
  301. printf("n");
  302. printf("Timer        Count  Duration  Last RTT      SRTT      Mdev   Methodn");
  303. switch(tcb->timer.state){
  304. case TIMER_STOP:
  305. printf("stopped");
  306. break;
  307. case TIMER_RUN:
  308. printf("running");
  309. break;
  310. case TIMER_EXPIRE:
  311. printf("expired");
  312. break;
  313. }
  314. printf(" %10lu%10lu%10lu%10lu%10lu",(long)read_timer(&tcb->timer),
  315.  (long)dur_timer(&tcb->timer),tcb->rtt,tcb->srtt,tcb->mdev);
  316. printf("   %sn",tcb->flags.ts_ok ? "timestamps":"standard");
  317. if(tcb->reseq != (struct reseq *)NULL){
  318. register struct reseq *rp;
  319. printf("Reassembly queue:n");
  320. for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
  321. printf("  seq x%lx %u bytesn",rp->seg.seq,rp->length);
  322. }
  323. }
  324. }
  325. static int
  326. keychar(c)
  327. int c;
  328. {
  329. if(c != CTLC)
  330. return 1; /* Ignore all but ^C */
  331. fprintf(Current->output,"^Cn");
  332. alert(Current->proc,EABORT);
  333. Current->inproc = NULL;
  334. return 0;
  335. }