tcp_usrreq.c
上传用户:tjbfgc
上传日期:2013-03-31
资源大小:140k
文件大小:13k
源码类别:

网络编程

开发平台:

C/C++

  1. /*
  2.  * Copyright (c) 1982, 1986, 1988, 1993
  3.  * The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  * This product includes software developed by the University of
  16.  * California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  * @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
  34.  */
  35. #include <sys/param.h>
  36. #include <sys/systm.h>
  37. #include <sys/malloc.h>
  38. #include <sys/mbuf.h>
  39. #include <sys/socket.h>
  40. #include <sys/socketvar.h>
  41. #include <sys/protosw.h>
  42. #include <sys/errno.h>
  43. #include <sys/stat.h>
  44. #include <net/if.h>
  45. #include <net/route.h>
  46. #include <netinet/in.h>
  47. #include <netinet/in_systm.h>
  48. #include <netinet/ip.h>
  49. #include <netinet/in_pcb.h>
  50. #include <netinet/ip_var.h>
  51. #include <netinet/tcp.h>
  52. #include <netinet/tcp_fsm.h>
  53. #include <netinet/tcp_seq.h>
  54. #include <netinet/tcp_timer.h>
  55. #include <netinet/tcp_var.h>
  56. #include <netinet/tcpip.h>
  57. #include <netinet/tcp_debug.h>
  58. /*
  59.  * TCP protocol interface to socket abstraction.
  60.  */
  61. extern char *tcpstates[];
  62. /*
  63.  * Process a TCP user request for TCP tb.  If this is a send request
  64.  * then m is the mbuf chain of send data.  If this is a timer expiration
  65.  * (called from the software clock routine), then timertype tells which timer.
  66.  */
  67. /*ARGSUSED*/
  68. int
  69. tcp_usrreq(so, req, m, nam, control)
  70. struct socket *so;
  71. int req;
  72. struct mbuf *m, *nam, *control;
  73. {
  74. register struct inpcb *inp;
  75. register struct tcpcb *tp;
  76. int s;
  77. int error = 0;
  78. int ostate;
  79. if (req == PRU_CONTROL)
  80. return (in_control(so, (int)m, (caddr_t)nam,
  81. (struct ifnet *)control));
  82. if (control && control->m_len) {
  83. m_freem(control);
  84. if (m)
  85. m_freem(m);
  86. return (EINVAL);
  87. }
  88. s = splnet();
  89. inp = sotoinpcb(so);
  90. /*
  91.  * When a TCP is attached to a socket, then there will be
  92.  * a (struct inpcb) pointed at by the socket, and this
  93.  * structure will point at a subsidary (struct tcpcb).
  94.  */
  95. if (inp == 0 && req != PRU_ATTACH) {
  96. splx(s);
  97. return (EINVAL); /* XXX */
  98. }
  99. if (inp) {
  100. tp = intotcpcb(inp);
  101. /* WHAT IF TP IS 0? */
  102. #ifdef KPROF
  103. tcp_acounts[tp->t_state][req]++;
  104. #endif
  105. ostate = tp->t_state;
  106. } else
  107. ostate = 0;
  108. switch (req) {
  109. /*
  110.  * TCP attaches to socket via PRU_ATTACH, reserving space,
  111.  * and an internet control block.
  112.  */
  113. case PRU_ATTACH:
  114. if (inp) {
  115. error = EISCONN;
  116. break;
  117. }
  118. error = tcp_attach(so);
  119. if (error)
  120. break;
  121. if ((so->so_options & SO_LINGER) && so->so_linger == 0)
  122. so->so_linger = TCP_LINGERTIME;
  123. tp = sototcpcb(so);
  124. break;
  125. /*
  126.  * PRU_DETACH detaches the TCP protocol from the socket.
  127.  * If the protocol state is non-embryonic, then can't
  128.  * do this directly: have to initiate a PRU_DISCONNECT,
  129.  * which may finish later; embryonic TCB's can just
  130.  * be discarded here.
  131.  */
  132. case PRU_DETACH:
  133. if (tp->t_state > TCPS_LISTEN)
  134. tp = tcp_disconnect(tp);
  135. else
  136. tp = tcp_close(tp);
  137. break;
  138. /*
  139.  * Give the socket an address.
  140.  */
  141. case PRU_BIND:
  142. error = in_pcbbind(inp, nam);
  143. if (error)
  144. break;
  145. break;
  146. /*
  147.  * Prepare to accept connections.
  148.  */
  149. case PRU_LISTEN:
  150. if (inp->inp_lport == 0)
  151. error = in_pcbbind(inp, (struct mbuf *)0);
  152. if (error == 0)
  153. tp->t_state = TCPS_LISTEN;
  154. break;
  155. /*
  156.  * Initiate connection to peer.
  157.  * Create a template for use in transmissions on this connection.
  158.  * Enter SYN_SENT state, and mark socket as connecting.
  159.  * Start keep-alive timer, and seed output sequence space.
  160.  * Send initial segment on connection.
  161.  */
  162. case PRU_CONNECT:
  163. if (inp->inp_lport == 0) {
  164. error = in_pcbbind(inp, (struct mbuf *)0);
  165. if (error)
  166. break;
  167. }
  168. error = in_pcbconnect(inp, nam);
  169. if (error)
  170. break;
  171. tp->t_template = tcp_template(tp);
  172. if (tp->t_template == 0) {
  173. in_pcbdisconnect(inp);
  174. error = ENOBUFS;
  175. break;
  176. }
  177. /* Compute window scaling to request.  */
  178. while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
  179.     (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
  180. tp->request_r_scale++;
  181. soisconnecting(so);
  182. tcpstat.tcps_connattempt++;
  183. tp->t_state = TCPS_SYN_SENT;
  184. tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
  185. tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
  186. tcp_sendseqinit(tp);
  187. error = tcp_output(tp);
  188. break;
  189. /*
  190.  * Create a TCP connection between two sockets.
  191.  */
  192. case PRU_CONNECT2:
  193. error = EOPNOTSUPP;
  194. break;
  195. /*
  196.  * Initiate disconnect from peer.
  197.  * If connection never passed embryonic stage, just drop;
  198.  * else if don't need to let data drain, then can just drop anyways,
  199.  * else have to begin TCP shutdown process: mark socket disconnecting,
  200.  * drain unread data, state switch to reflect user close, and
  201.  * send segment (e.g. FIN) to peer.  Socket will be really disconnected
  202.  * when peer sends FIN and acks ours.
  203.  *
  204.  * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
  205.  */
  206. case PRU_DISCONNECT:
  207. tp = tcp_disconnect(tp);
  208. break;
  209. /*
  210.  * Accept a connection.  Essentially all the work is
  211.  * done at higher levels; just return the address
  212.  * of the peer, storing through addr.
  213.  */
  214. case PRU_ACCEPT:
  215. in_setpeeraddr(inp, nam);
  216. break;
  217. /*
  218.  * Mark the connection as being incapable of further output.
  219.  */
  220. case PRU_SHUTDOWN:
  221. socantsendmore(so);
  222. tp = tcp_usrclosed(tp);
  223. if (tp)
  224. error = tcp_output(tp);
  225. break;
  226. /*
  227.  * After a receive, possibly send window update to peer.
  228.  */
  229. case PRU_RCVD:
  230. (void) tcp_output(tp);
  231. break;
  232. /*
  233.  * Do a send by putting data in output queue and updating urgent
  234.  * marker if URG set.  Possibly send more data.
  235.  */
  236. case PRU_SEND:
  237. sbappend(&so->so_snd, m);
  238. error = tcp_output(tp);
  239. break;
  240. /*
  241.  * Abort the TCP.
  242.  */
  243. case PRU_ABORT:
  244. tp = tcp_drop(tp, ECONNABORTED);
  245. break;
  246. case PRU_SENSE:
  247. ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;
  248. (void) splx(s);
  249. return (0);
  250. case PRU_RCVOOB:
  251. if ((so->so_oobmark == 0 &&
  252.     (so->so_state & SS_RCVATMARK) == 0) ||
  253.     so->so_options & SO_OOBINLINE ||
  254.     tp->t_oobflags & TCPOOB_HADDATA) {
  255. error = EINVAL;
  256. break;
  257. }
  258. if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) {
  259. error = EWOULDBLOCK;
  260. break;
  261. }
  262. m->m_len = 1;
  263. *mtod(m, caddr_t) = tp->t_iobc;
  264. if (((int)nam & MSG_PEEK) == 0)
  265. tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA);
  266. break;
  267. case PRU_SENDOOB:
  268. if (sbspace(&so->so_snd) < -512) {
  269. m_freem(m);
  270. error = ENOBUFS;
  271. break;
  272. }
  273. /*
  274.  * According to RFC961 (Assigned Protocols),
  275.  * the urgent pointer points to the last octet
  276.  * of urgent data.  We continue, however,
  277.  * to consider it to indicate the first octet
  278.  * of data past the urgent section.
  279.  * Otherwise, snd_up should be one lower.
  280.  */
  281. sbappend(&so->so_snd, m);
  282. tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
  283. tp->t_force = 1;
  284. error = tcp_output(tp);
  285. tp->t_force = 0;
  286. break;
  287. case PRU_SOCKADDR:
  288. in_setsockaddr(inp, nam);
  289. break;
  290. case PRU_PEERADDR:
  291. in_setpeeraddr(inp, nam);
  292. break;
  293. /*
  294.  * TCP slow timer went off; going through this
  295.  * routine for tracing's sake.
  296.  */
  297. case PRU_SLOWTIMO:
  298. tp = tcp_timers(tp, (int)nam);
  299. req |= (int)nam << 8; /* for debug's sake */
  300. break;
  301. default:
  302. panic("tcp_usrreq");
  303. }
  304. if (tp && (so->so_options & SO_DEBUG))
  305. tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req);
  306. splx(s);
  307. return (error);
  308. }
  309. int
  310. tcp_ctloutput(op, so, level, optname, mp)
  311. int op;
  312. struct socket *so;
  313. int level, optname;
  314. struct mbuf **mp;
  315. {
  316. int error = 0, s;
  317. struct inpcb *inp;
  318. register struct tcpcb *tp;
  319. register struct mbuf *m;
  320. register int i;
  321. s = splnet();
  322. inp = sotoinpcb(so);
  323. if (inp == NULL) {
  324. splx(s);
  325. if (op == PRCO_SETOPT && *mp)
  326. (void) m_free(*mp);
  327. return (ECONNRESET);
  328. }
  329. if (level != IPPROTO_TCP) {
  330. error = ip_ctloutput(op, so, level, optname, mp);
  331. splx(s);
  332. return (error);
  333. }
  334. tp = intotcpcb(inp);
  335. switch (op) {
  336. case PRCO_SETOPT:
  337. m = *mp;
  338. switch (optname) {
  339. case TCP_NODELAY:
  340. if (m == NULL || m->m_len < sizeof (int))
  341. error = EINVAL;
  342. else if (*mtod(m, int *))
  343. tp->t_flags |= TF_NODELAY;
  344. else
  345. tp->t_flags &= ~TF_NODELAY;
  346. break;
  347. case TCP_MAXSEG:
  348. if (m && (i = *mtod(m, int *)) > 0 && i <= tp->t_maxseg)
  349. tp->t_maxseg = i;
  350. else
  351. error = EINVAL;
  352. break;
  353. default:
  354. error = ENOPROTOOPT;
  355. break;
  356. }
  357. if (m)
  358. (void) m_free(m);
  359. break;
  360. case PRCO_GETOPT:
  361. *mp = m = m_get(M_WAIT, MT_SOOPTS);
  362. m->m_len = sizeof(int);
  363. switch (optname) {
  364. case TCP_NODELAY:
  365. *mtod(m, int *) = tp->t_flags & TF_NODELAY;
  366. break;
  367. case TCP_MAXSEG:
  368. *mtod(m, int *) = tp->t_maxseg;
  369. break;
  370. default:
  371. error = ENOPROTOOPT;
  372. break;
  373. }
  374. break;
  375. }
  376. splx(s);
  377. return (error);
  378. }
  379. u_long tcp_sendspace = 1024*8;
  380. u_long tcp_recvspace = 1024*8;
  381. /*
  382.  * Attach TCP protocol to socket, allocating
  383.  * internet protocol control block, tcp control block,
  384.  * bufer space, and entering LISTEN state if to accept connections.
  385.  */
  386. int
  387. tcp_attach(so)
  388. struct socket *so;
  389. {
  390. register struct tcpcb *tp;
  391. struct inpcb *inp;
  392. int error;
  393. if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  394. error = soreserve(so, tcp_sendspace, tcp_recvspace);
  395. if (error)
  396. return (error);
  397. }
  398. error = in_pcballoc(so, &tcb);
  399. if (error)
  400. return (error);
  401. inp = sotoinpcb(so);
  402. tp = tcp_newtcpcb(inp);
  403. if (tp == 0) {
  404. int nofd = so->so_state & SS_NOFDREF; /* XXX */
  405. so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */
  406. in_pcbdetach(inp);
  407. so->so_state |= nofd;
  408. return (ENOBUFS);
  409. }
  410. tp->t_state = TCPS_CLOSED;
  411. return (0);
  412. }
  413. /*
  414.  * Initiate (or continue) disconnect.
  415.  * If embryonic state, just send reset (once).
  416.  * If in ``let data drain'' option and linger null, just drop.
  417.  * Otherwise (hard), mark socket disconnecting and drop
  418.  * current input data; switch states based on user close, and
  419.  * send segment to peer (with FIN).
  420.  */
  421. struct tcpcb *
  422. tcp_disconnect(tp)
  423. register struct tcpcb *tp;
  424. {
  425. struct socket *so = tp->t_inpcb->inp_socket;
  426. if (tp->t_state < TCPS_ESTABLISHED)
  427. tp = tcp_close(tp);
  428. else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
  429. tp = tcp_drop(tp, 0);
  430. else {
  431. soisdisconnecting(so);
  432. sbflush(&so->so_rcv);
  433. tp = tcp_usrclosed(tp);
  434. if (tp)
  435. (void) tcp_output(tp);
  436. }
  437. return (tp);
  438. }
  439. /*
  440.  * User issued close, and wish to trail through shutdown states:
  441.  * if never received SYN, just forget it.  If got a SYN from peer,
  442.  * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
  443.  * If already got a FIN from peer, then almost done; go to LAST_ACK
  444.  * state.  In all other cases, have already sent FIN to peer (e.g.
  445.  * after PRU_SHUTDOWN), and just have to play tedious game waiting
  446.  * for peer to send FIN or not respond to keep-alives, etc.
  447.  * We can let the user exit from the close as soon as the FIN is acked.
  448.  */
  449. struct tcpcb *
  450. tcp_usrclosed(tp)
  451. register struct tcpcb *tp;
  452. {
  453. switch (tp->t_state) {
  454. case TCPS_CLOSED:
  455. case TCPS_LISTEN:
  456. case TCPS_SYN_SENT:
  457. tp->t_state = TCPS_CLOSED;
  458. tp = tcp_close(tp);
  459. break;
  460. case TCPS_SYN_RECEIVED:
  461. case TCPS_ESTABLISHED:
  462. tp->t_state = TCPS_FIN_WAIT_1;
  463. break;
  464. case TCPS_CLOSE_WAIT:
  465. tp->t_state = TCPS_LAST_ACK;
  466. break;
  467. }
  468. if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
  469. soisdisconnected(tp->t_inpcb->inp_socket);
  470. return (tp);
  471. }