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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* User calls to TCP
  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 "socket.h"
  10. #include "internet.h"
  11. #include "tcp.h"
  12. #include "ip.h"
  13. #include "icmp.h"
  14. #include "proc.h"
  15. uint16 Tcp_window = DEF_WND;
  16. struct tcb *
  17. open_tcp(lsocket,fsocket,mode,window,r_upcall,t_upcall,s_upcall,tos,user)
  18. struct socket *lsocket; /* Local socket */
  19. struct socket *fsocket; /* Remote socket */
  20. int mode; /* Active/passive/server */
  21. uint16 window; /* Receive window (and send buffer) sizes */
  22. void (*r_upcall)(); /* Function to call when data arrives */
  23. void (*t_upcall)(); /* Function to call when ok to send more data */
  24. void (*s_upcall)(); /* Function to call when connection state changes */
  25. int tos;
  26. int user; /* User linkage area */
  27. {
  28. struct connection conn;
  29. register struct tcb *tcb;
  30. if(lsocket == NULL){
  31. Net_error = INVALID;
  32. return NULL;
  33. }
  34. conn.local.address = lsocket->address;
  35. conn.local.port = lsocket->port;
  36. if(fsocket != NULL){
  37. conn.remote.address = fsocket->address;
  38. conn.remote.port = fsocket->port;
  39. } else {
  40. conn.remote.address = 0;
  41. conn.remote.port = 0;
  42. }
  43. if((tcb = lookup_tcb(&conn)) == NULL){
  44. if((tcb = create_tcb(&conn)) == NULL){
  45. Net_error = NO_MEM;
  46. return NULL;
  47. }
  48. } else if(tcb->state != TCP_LISTEN){
  49. Net_error = CON_EXISTS;
  50. return NULL;
  51. }
  52. tcb->user = user;
  53. if(window != 0)
  54. tcb->window = tcb->rcv.wnd = window;
  55. else
  56. tcb->window = tcb->rcv.wnd = Tcp_window;
  57. tcb->snd.wnd = 1; /* Allow space for sending a SYN */
  58. tcb->r_upcall = r_upcall;
  59. tcb->t_upcall = t_upcall;
  60. tcb->s_upcall = s_upcall;
  61. tcb->tos = tos;
  62. switch(mode){
  63. case TCP_SERVER:
  64. tcb->flags.clone = 1;
  65. case TCP_PASSIVE: /* Note fall-thru */
  66. settcpstate(tcb,TCP_LISTEN);
  67. break;
  68. case TCP_ACTIVE:
  69. /* Send SYN, go into TCP_SYN_SENT state */
  70. tcb->flags.active = 1;
  71. send_syn(tcb);
  72. settcpstate(tcb,TCP_SYN_SENT);
  73. tcp_output(tcb);
  74. break;
  75. }
  76. return tcb;
  77. }
  78. /* User send routine */
  79. long
  80. send_tcp(tcb,bpp)
  81. register struct tcb *tcb;
  82. struct mbuf **bpp;
  83. {
  84. int32 cnt;
  85. if(tcb == NULL || bpp == NULL || *bpp == NULL){
  86. free_p(bpp);
  87. Net_error = INVALID;
  88. return -1;
  89. }
  90. cnt = len_p(*bpp);
  91. switch(tcb->state){
  92. case TCP_CLOSED:
  93. free_p(bpp);
  94. Net_error = NO_CONN;
  95. return -1;
  96. case TCP_LISTEN:
  97. if(tcb->conn.remote.address == 0 && tcb->conn.remote.port == 0){
  98. /* Save data for later */
  99. append(&tcb->sndq,bpp);
  100. tcb->sndcnt += cnt;
  101. break;
  102. }
  103. /* Change state from passive to active */
  104. tcb->flags.active = 1;
  105. send_syn(tcb);
  106. settcpstate(tcb,TCP_SYN_SENT); /* Note fall-thru */
  107. case TCP_SYN_SENT:
  108. case TCP_SYN_RECEIVED:
  109. case TCP_ESTABLISHED:
  110. case TCP_CLOSE_WAIT:
  111. append(&tcb->sndq,bpp);
  112. tcb->sndcnt += cnt;
  113. tcp_output(tcb);
  114. break;
  115. case TCP_FINWAIT1:
  116. case TCP_FINWAIT2:
  117. case TCP_CLOSING:
  118. case TCP_LAST_ACK:
  119. case TCP_TIME_WAIT:
  120. free_p(bpp);
  121. Net_error = CON_CLOS;
  122. return -1;
  123. }
  124. return (long)cnt;
  125. }
  126. /* User receive routine */
  127. int32
  128. recv_tcp(tcb,bpp,cnt)
  129. register struct tcb *tcb;
  130. struct mbuf **bpp;
  131. int32 cnt;
  132. {
  133. if(tcb == NULL || bpp == (struct mbuf **)NULL){
  134. Net_error = INVALID;
  135. return -1;
  136. }
  137. if(tcb->rcvcnt == 0){
  138. /* If there's nothing on the queue, our action depends on what state
  139.  * we're in (i.e., whether or not we're expecting any more data).
  140.  * If no more data is expected, then simply return 0; this is
  141.  * interpreted as "end of file". Otherwise return -1.
  142.  */
  143. switch(tcb->state){
  144. case TCP_LISTEN:
  145. case TCP_SYN_SENT:
  146. case TCP_SYN_RECEIVED:
  147. case TCP_ESTABLISHED:
  148. case TCP_FINWAIT1:
  149. case TCP_FINWAIT2:
  150. Net_error = WOULDBLK;
  151. return -1;
  152. case TCP_CLOSED:
  153. case TCP_CLOSE_WAIT:
  154. case TCP_CLOSING:
  155. case TCP_LAST_ACK:
  156. case TCP_TIME_WAIT:
  157. *bpp = NULL;
  158. return 0;
  159. }
  160. }
  161. /* cnt == 0 means "I want it all" */
  162. if(cnt == 0)
  163. cnt = tcb->rcvcnt;
  164. /* See if the user can take all of it */
  165. if(tcb->rcvcnt <= cnt){
  166. cnt = tcb->rcvcnt;
  167. *bpp = tcb->rcvq;
  168. tcb->rcvq = NULL;
  169. } else {
  170. *bpp = ambufw(cnt);
  171. pullup(&tcb->rcvq,(*bpp)->data,cnt);
  172. (*bpp)->cnt = cnt;
  173. }
  174. tcb->rcvcnt -= cnt;
  175. tcb->rcv.wnd += cnt;
  176. /* Do a window update if it was less than one packet and now it's more */
  177. if(tcb->rcv.wnd > tcb->mss && tcb->rcv.wnd - cnt < tcb->mss){
  178. tcb->flags.force = 1;
  179. tcp_output(tcb);
  180. }
  181. return (int)cnt;
  182. }
  183. /* This really means "I have no more data to send". It only closes the
  184.  * connection in one direction, and we can continue to receive data
  185.  * indefinitely.
  186.  */
  187. int
  188. close_tcp(tcb)
  189. register struct tcb *tcb;
  190. {
  191. if(tcb == NULL){
  192. Net_error = INVALID;
  193. return -1;
  194. }
  195. switch(tcb->state){
  196. case TCP_CLOSED:
  197. return 0; /* Unlikely */
  198. case TCP_LISTEN:
  199. case TCP_SYN_SENT:
  200. close_self(tcb,NORMAL);
  201. return 0;
  202. case TCP_SYN_RECEIVED:
  203. case TCP_ESTABLISHED:
  204. tcb->sndcnt++;
  205. tcb->snd.nxt++;
  206. settcpstate(tcb,TCP_FINWAIT1);
  207. tcp_output(tcb);
  208. return 0;
  209. case TCP_CLOSE_WAIT:
  210. tcb->sndcnt++;
  211. tcb->snd.nxt++;
  212. settcpstate(tcb,TCP_LAST_ACK);
  213. tcp_output(tcb);
  214. return 0;
  215. case TCP_FINWAIT1:
  216. case TCP_FINWAIT2:
  217. case TCP_CLOSING:
  218. case TCP_LAST_ACK:
  219. case TCP_TIME_WAIT:
  220. Net_error = CON_CLOS;
  221. return -1;
  222. }
  223. return -1; /* "Can't happen" */
  224. }
  225. /* Delete TCB, free resources. The user is not notified, even if the TCB is
  226.  * not in the TCP_CLOSED state. This function should normally be called by the
  227.  * user only in response to a state change upcall to TCP_CLOSED state.
  228.  */
  229. int
  230. del_tcp(conn)
  231. struct tcb *conn;
  232. {
  233. register struct tcb *tcb;
  234. struct tcb *tcblast = NULL;
  235. struct reseq *rp,*rp1;
  236. /* Remove from list */
  237. for(tcb=Tcbs;tcb != NULL;tcblast = tcb,tcb = tcb->next)
  238. if(tcb == conn)
  239. break;
  240. if(tcb == NULL){
  241. Net_error = INVALID;
  242. return -1; /* conn was NULL, or not on list */ 
  243. }
  244. if(tcblast != NULL)
  245. tcblast->next = tcb->next;
  246. else
  247. Tcbs = tcb->next; /* was first on list */
  248. stop_timer(&tcb->timer);
  249. for(rp = tcb->reseq;rp != NULL;rp = rp1){
  250. rp1 = rp->next;
  251. free_p(&rp->bp);
  252. free(rp);
  253. }
  254. tcb->reseq = NULL;
  255. free_p(&tcb->rcvq);
  256. free_p(&tcb->sndq);
  257. free(tcb);
  258. return 0;
  259. }
  260. /* Return 1 if arg is a valid TCB, 0 otherwise */
  261. int
  262. tcpval(tcb)
  263. struct tcb *tcb;
  264. {
  265. register struct tcb *tcb1;
  266. if(tcb == NULL)
  267. return 0; /* Null pointer can't be valid */
  268. for(tcb1=Tcbs;tcb1 != NULL;tcb1 = tcb1->next){
  269. if(tcb1 == tcb)
  270. return 1;
  271. }
  272. return 0;
  273. }
  274. /* Kick a particular TCP connection */
  275. int
  276. kick_tcp(tcb)
  277. register struct tcb *tcb;
  278. {
  279. if(!tcpval(tcb))
  280. return -1;
  281. tcb->flags.force = 1; /* Send ACK even if no data */
  282. tcb->backoff = 0;
  283. tcp_timeout(tcb);
  284. return 0;
  285. }
  286. /* Kick all TCP connections to specified address; return number kicked */
  287. int
  288. kick(addr)
  289. int32 addr;
  290. {
  291. register struct tcb *tcb;
  292. int cnt = 0;
  293. for(tcb=Tcbs;tcb != NULL;tcb = tcb->next){
  294. if(tcb->conn.remote.address == addr){
  295. kick_tcp(tcb);
  296. cnt++;
  297. }
  298. }
  299. return cnt;
  300. }
  301. /* Clear all TCP connections */
  302. void
  303. reset_all()
  304. {
  305. register struct tcb *tcb,*tcbnext;
  306. for(tcb=Tcbs;tcb != NULL;tcb = tcbnext){
  307. tcbnext = tcb->next;
  308. reset_tcp(tcb);
  309. }
  310. kwait(NULL); /* Let the RSTs go forth */
  311. }
  312. void
  313. reset_tcp(tcb)
  314. register struct tcb *tcb;
  315. {
  316. struct tcp fakeseg;
  317. struct ip fakeip;
  318. if(tcb == NULL)
  319. return;
  320. if(tcb->state != TCP_LISTEN){
  321. /* Compose a fake segment with just enough info to generate the
  322.  * correct RST reply
  323.  */
  324. memset(&fakeseg,0,sizeof(fakeseg));
  325. memset(&fakeip,0,sizeof(fakeip));
  326. fakeseg.dest = tcb->conn.local.port;
  327. fakeseg.source = tcb->conn.remote.port;
  328. fakeseg.flags.ack = 1;
  329. /* Here we try to pick a sequence number with the greatest likelihood
  330.  * of being in his receive window.
  331.  */
  332. fakeseg.ack = tcb->snd.nxt + tcb->snd.wnd - 1;
  333. fakeip.dest = tcb->conn.local.address;
  334. fakeip.source = tcb->conn.remote.address;
  335. fakeip.tos = tcb->tos;
  336. reset(&fakeip,&fakeseg);
  337. }
  338. close_self(tcb,RESET);
  339. }
  340. #ifdef notused
  341. /* Return character string corresponding to a TCP well-known port, or
  342.  * the decimal number if unknown.
  343.  */
  344. char *
  345. tcp_port(n)
  346. uint16 n;
  347. {
  348. static char buf[32];
  349. switch(n){
  350. case IPPORT_ECHO:
  351. return "echo";
  352. case IPPORT_DISCARD:
  353. return "discard";
  354. case IPPORT_FTPD:
  355. return "ftp_data";
  356. case IPPORT_FTP:
  357. return "ftp";
  358. case IPPORT_TELNET:
  359. return "telnet";
  360. case IPPORT_SMTP:
  361. return "smtp";
  362. case IPPORT_POP:
  363. return "pop";
  364. default:
  365. sprintf(buf,"%u",n);
  366. return buf;
  367. }
  368. }
  369. #endif