8 #include <gpxe/pkbuff.h>
9 #include <gpxe/retry.h>
10 #include <gpxe/tcpip.h>
19 static void tcp_expired ( struct retry_timer *timer, int over );
20 static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send );
25 * This data structure represents the internal state of a TCP
26 * connection. It is kept separate from @c struct @c tcp_application
27 * because the internal state is still required for some time after
28 * the application closes the connection.
30 struct tcp_connection {
31 /** List of TCP connections */
32 struct list_head list;
33 /** The associated TCP application, if any */
34 struct tcp_application *app;
36 /** Remote socket address */
37 struct sockaddr_tcpip peer;
38 /** Local port, in network byte order */
41 /** Current TCP state */
42 unsigned int tcp_state;
43 /** Previous TCP state
45 * Maintained only for debug messages
47 unsigned int prev_tcp_state;
48 /** Current sequence number
50 * Equivalent to SND.UNA in RFC 793 terminology.
53 /** Unacknowledged sequence count
55 * Equivalent to (SND.NXT-SND.UNA) in RFC 793 terminology.
60 * Equivalent to SND.WND in RFC 793 terminology
63 /** Current acknowledgement number
65 * Equivalent to RCV.NXT in RFC 793 terminology.
69 /** Transmit packet buffer
71 * This buffer is allocated prior to calling the application's
72 * senddata() method, to provide temporary storage space.
74 struct pk_buff *tx_pkb;
75 /** Retransmission timer */
76 struct retry_timer timer;
80 * List of registered TCP connections
82 static LIST_HEAD ( tcp_conns );
88 * @ret name Name of TCP state
90 static inline __attribute__ (( always_inline )) const char *
91 tcp_state ( int state ) {
93 case TCP_CLOSED: return "CLOSED";
94 case TCP_LISTEN: return "LISTEN";
95 case TCP_SYN_SENT: return "SYN_SENT";
96 case TCP_SYN_RCVD: return "SYN_RCVD";
97 case TCP_ESTABLISHED: return "ESTABLISHED";
98 case TCP_FIN_WAIT_1: return "FIN_WAIT_1";
99 case TCP_FIN_WAIT_2: return "FIN_WAIT_2";
100 case TCP_CLOSING_OR_LAST_ACK: return "CLOSING/LAST_ACK";
101 case TCP_TIME_WAIT: return "TIME_WAIT";
102 case TCP_CLOSE_WAIT: return "CLOSE_WAIT";
103 default: return "INVALID";
108 * Dump TCP state transition
110 * @v conn TCP connection
112 static inline __attribute__ (( always_inline )) void
113 tcp_dump_state ( struct tcp_connection *conn ) {
115 if ( conn->tcp_state != conn->prev_tcp_state ) {
116 DBGC ( conn, "TCP %p transitioned from %s to %s\n", conn,
117 tcp_state ( conn->prev_tcp_state ),
118 tcp_state ( conn->tcp_state ) );
120 conn->prev_tcp_state = conn->tcp_state;
128 static inline __attribute__ (( always_inline )) void
129 tcp_dump_flags ( struct tcp_connection *conn, unsigned int flags ) {
130 if ( flags & TCP_RST )
131 DBGC ( conn, " RST" );
132 if ( flags & TCP_SYN )
133 DBGC ( conn, " SYN" );
134 if ( flags & TCP_PSH )
135 DBGC ( conn, " PSH" );
136 if ( flags & TCP_FIN )
137 DBGC ( conn, " FIN" );
138 if ( flags & TCP_ACK )
139 DBGC ( conn, " ACK" );
143 * Allocate TCP connection
145 * @ret conn TCP connection, or NULL
147 * Allocates TCP connection and adds it to the TCP connection list.
149 static struct tcp_connection * alloc_tcp ( void ) {
150 struct tcp_connection *conn;
152 conn = calloc ( 1, sizeof ( *conn ) );
154 DBGC ( conn, "TCP %p allocated\n", conn );
155 conn->tcp_state = conn->prev_tcp_state = TCP_CLOSED;
156 conn->snd_seq = random();
157 conn->timer.expired = tcp_expired;
158 list_add ( &conn->list, &tcp_conns );
164 * Free TCP connection
166 * @v conn TCP connection
168 * Removes connection from TCP connection list and frees the data
171 static void free_tcp ( struct tcp_connection *conn ) {
174 assert ( conn->tcp_state == TCP_CLOSED );
175 assert ( conn->app == NULL );
177 stop_timer ( &conn->timer );
178 list_del ( &conn->list );
180 DBGC ( conn, "TCP %p freed\n", conn );
184 * Associate TCP connection with application
186 * @v conn TCP connection
187 * @v app TCP application
189 static void tcp_associate ( struct tcp_connection *conn,
190 struct tcp_application *app ) {
191 assert ( conn->app == NULL );
192 assert ( app->conn == NULL );
195 DBGC ( conn, "TCP %p associated with application %p\n", conn, app );
199 * Disassociate TCP connection from application
201 * @v conn TCP connection
203 static void tcp_disassociate ( struct tcp_connection *conn ) {
204 struct tcp_application *app = conn->app;
207 assert ( app->conn == conn );
210 DBGC ( conn, "TCP %p disassociated from application %p\n",
216 * Abort TCP connection
218 * @v conn TCP connection
219 * @v send_rst Send a RST after closing
222 static void tcp_abort ( struct tcp_connection *conn, int send_rst, int rc ) {
223 struct tcp_application *app = conn->app;
225 /* Transition to CLOSED */
226 conn->tcp_state = TCP_CLOSED;
227 tcp_dump_state ( conn );
229 /* Send RST if requested to do so */
231 tcp_senddata_conn ( conn, 1 );
233 /* Break association between application and connection */
234 tcp_disassociate ( conn );
236 /* Free the connection */
239 /* Notify application */
240 if ( app && app->tcp_op->closed )
241 app->tcp_op->closed ( app, rc );
245 * Transmit any outstanding data
247 * @v conn TCP connection
248 * @v force_send Force sending of packet
250 * Transmits any outstanding data on the connection. If the
251 * connection is in a connected state, the application's senddata()
252 * method will be called to generate the data payload, if any.
254 * Note that even if an error is returned, the retransmission timer
255 * will have been started if necessary, and so the stack will
256 * eventually attempt to retransmit the failed packet.
258 static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
259 struct tcp_application *app = conn->app;
261 struct tcp_header *tcphdr;
262 struct tcp_mss_option *mssopt;
269 /* Allocate space to the TX buffer */
270 pkb = alloc_pkb ( MAX_PKB_LEN );
272 DBGC ( conn, "TCP %p could not allocate data buffer\n", conn );
273 /* Start the retry timer so that we attempt to
274 * retransmit this packet later. (Start it
275 * unconditionally, since without a packet buffer we
276 * can't call the senddata() callback, and so may not
277 * be able to tell whether or not we have something
278 * that actually needs to be retransmitted).
280 start_timer ( &conn->timer );
283 pkb_reserve ( pkb, MAX_HDR_LEN );
285 /* If we are connected, call the senddata() method, which may
286 * call tcp_send() to queue up a data payload.
288 if ( TCP_CAN_SEND_DATA ( conn->tcp_state ) &&
289 app && app->tcp_op->senddata ) {
291 app->tcp_op->senddata ( app, pkb->data, pkb_tailroom ( pkb ) );
295 /* Truncate payload length to fit transmit window */
296 len = pkb_len ( pkb );
297 if ( len > conn->snd_win )
300 /* Calculate amount of sequence space that this transmission
301 * consumes. (SYN or FIN consume one byte, and we can never
302 * send both at once).
305 flags = TCP_FLAGS_SENDING ( conn->tcp_state );
306 assert ( ! ( ( flags & TCP_SYN ) && ( flags & TCP_FIN ) ) );
307 if ( flags & ( TCP_SYN | TCP_FIN ) )
309 conn->snd_sent = seq_len;
311 /* If we have nothing to transmit, drop the packet */
312 if ( ( seq_len == 0 ) && ! force_send ) {
317 /* If we are transmitting anything that requires
318 * acknowledgement (i.e. consumes sequence space), start the
319 * retransmission timer.
322 start_timer ( &conn->timer );
324 /* Fill up the TCP header */
326 if ( flags & TCP_SYN ) {
327 mssopt = pkb_push ( pkb, sizeof ( *mssopt ) );
328 mssopt->kind = TCP_OPTION_MSS;
329 mssopt->length = sizeof ( *mssopt );
330 mssopt->mss = htons ( TCP_MSS );
332 tcphdr = pkb_push ( pkb, sizeof ( *tcphdr ) );
333 memset ( tcphdr, 0, sizeof ( *tcphdr ) );
334 tcphdr->src = conn->local_port;
335 tcphdr->dest = conn->peer.st_port;
336 tcphdr->seq = htonl ( conn->snd_seq );
337 tcphdr->ack = htonl ( conn->rcv_ack );
338 tcphdr->hlen = ( ( payload - pkb->data ) << 2 );
339 tcphdr->flags = flags;
340 tcphdr->win = htons ( TCP_WINDOW_SIZE );
341 tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
344 DBGC ( conn, "TCP %p TX %d->%d %08lx..%08lx %08lx %4zd",
345 conn, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
346 ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) + seq_len ),
347 ntohl ( tcphdr->ack ), len );
348 tcp_dump_flags ( conn, tcphdr->flags );
351 /* Transmit packet */
352 rc = tcpip_tx ( pkb, &tcp_protocol, &conn->peer, NULL, &tcphdr->csum );
354 /* If we got -ENETUNREACH, kill the connection immediately
355 * because there is no point retrying. This isn't strictly
356 * necessary (since we will eventually time out anyway), but
357 * it avoids irritating needless delays. Don't do this for
358 * RST packets transmitted on connection abort, to avoid a
359 * potential infinite loop.
361 if ( ( ! ( conn->tcp_state & TCP_STATE_SENT ( TCP_RST ) ) ) &&
362 ( rc == -ENETUNREACH ) ) {
363 DBGC ( conn, "TCP %p aborting after TX failed: %s\n",
364 conn, strerror ( rc ) );
365 tcp_abort ( conn, 0, rc );
372 * Transmit any outstanding data
374 * @v conn TCP connection
376 * This function allocates space to the transmit buffer and invokes
377 * the senddata() callback function, to allow the application to
380 int tcp_senddata ( struct tcp_application *app ) {
381 struct tcp_connection *conn = app->conn;
383 /* Check connection actually exists */
385 DBG ( "TCP app %p has no connection\n", app );
389 return tcp_senddata_conn ( conn, 0 );
395 * @v app TCP application
396 * @v data Data to be sent
397 * @v len Length of the data
398 * @ret rc Return status code
400 * This function queues data to be sent via the TCP connection. It
401 * can be called only in the context of an application's senddata()
404 int tcp_send ( struct tcp_application *app, const void *data, size_t len ) {
405 struct tcp_connection *conn = app->conn;
408 /* Check connection actually exists */
410 DBG ( "TCP app %p has no connection\n", app );
414 /* Check that we have a packet buffer to fill */
417 DBG ( "TCP app %p tried to send data outside of the "
418 "senddata() method\n", app );
422 /* Truncate length to fit packet buffer */
423 if ( len > pkb_tailroom ( pkb ) )
424 len = pkb_tailroom ( pkb );
427 memmove ( pkb_put ( pkb, len ), data, len );
433 * Retransmission timer expired
435 * @v timer Retry timer
436 * @v over Failure indicator
438 static void tcp_expired ( struct retry_timer *timer, int over ) {
439 struct tcp_connection *conn =
440 container_of ( timer, struct tcp_connection, timer );
441 int graceful_close = TCP_CLOSED_GRACEFULLY ( conn->tcp_state );
443 DBGC ( conn, "TCP %p timer %s in %s\n", conn,
444 ( over ? "expired" : "fired" ), tcp_state ( conn->tcp_state ) );
446 assert ( ( conn->tcp_state == TCP_SYN_SENT ) ||
447 ( conn->tcp_state == TCP_SYN_RCVD ) ||
448 ( conn->tcp_state == TCP_ESTABLISHED ) ||
449 ( conn->tcp_state == TCP_FIN_WAIT_1 ) ||
450 ( conn->tcp_state == TCP_TIME_WAIT ) ||
451 ( conn->tcp_state == TCP_CLOSE_WAIT ) ||
452 ( conn->tcp_state == TCP_CLOSING_OR_LAST_ACK ) );
454 if ( over || graceful_close ) {
455 /* If we have finally timed out and given up, or if
456 * this is the result of a graceful close, terminate
459 tcp_abort ( conn, 1, -ETIMEDOUT );
461 /* Otherwise, retransmit the packet */
462 tcp_senddata_conn ( conn, 0 );
467 * Send RST response to incoming packet
469 * @v in_tcphdr TCP header of incoming packet
470 * @ret rc Return status code
472 static int tcp_send_reset ( struct tcp_connection *conn,
473 struct tcp_header *in_tcphdr ) {
475 struct tcp_header *tcphdr;
477 /* Allocate space for dataless TX buffer */
478 pkb = alloc_pkb ( MAX_HDR_LEN );
480 DBGC ( conn, "TCP %p could not allocate data buffer\n", conn );
483 pkb_reserve ( pkb, MAX_HDR_LEN );
485 /* Construct RST response */
486 tcphdr = pkb_push ( pkb, sizeof ( *tcphdr ) );
487 memset ( tcphdr, 0, sizeof ( *tcphdr ) );
488 tcphdr->src = in_tcphdr->dest;
489 tcphdr->dest = in_tcphdr->src;
490 tcphdr->seq = in_tcphdr->ack;
491 tcphdr->ack = in_tcphdr->seq;
492 tcphdr->hlen = ( ( sizeof ( *tcphdr ) / 4 ) << 4 );
493 tcphdr->flags = ( TCP_RST | TCP_ACK );
494 tcphdr->win = htons ( TCP_WINDOW_SIZE );
495 tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
498 DBGC ( conn, "TCP %p TX %d->%d %08lx..%08lx %08lx %4zd",
499 conn, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
500 ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) ),
501 ntohl ( tcphdr->ack ), 0 );
502 tcp_dump_flags ( conn, tcphdr->flags );
505 /* Transmit packet */
506 return tcpip_tx ( pkb, &tcp_protocol, &conn->peer,
507 NULL, &tcphdr->csum );
511 * Identify TCP connection by local port number
513 * @v local_port Local port (in network-endian order)
514 * @ret conn TCP connection, or NULL
516 static struct tcp_connection * tcp_demux ( uint16_t local_port ) {
517 struct tcp_connection *conn;
519 list_for_each_entry ( conn, &tcp_conns, list ) {
520 if ( conn->local_port == local_port )
527 * Handle TCP received SYN
529 * @v conn TCP connection
530 * @v seq SEQ value (in host-endian order)
531 * @ret rc Return status code
533 static int tcp_rx_syn ( struct tcp_connection *conn, uint32_t seq ) {
534 struct tcp_application *app = conn->app;
536 /* Synchronise sequence numbers on first SYN */
537 if ( ! ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) )
540 /* Ignore duplicate SYN */
541 if ( ( conn->rcv_ack - seq ) > 0 )
544 /* Mark SYN as received and start sending ACKs with each packet */
545 conn->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
546 TCP_STATE_RCVD ( TCP_SYN ) );
548 /* Acknowledge SYN */
551 /* Notify application of established connection, if applicable */
552 if ( ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) &&
553 app && app->tcp_op->connected )
554 app->tcp_op->connected ( app );
560 * Handle TCP received ACK
562 * @v conn TCP connection
563 * @v ack ACK value (in host-endian order)
564 * @v win WIN value (in host-endian order)
565 * @ret rc Return status code
567 static int tcp_rx_ack ( struct tcp_connection *conn, uint32_t ack,
569 struct tcp_application *app = conn->app;
570 size_t ack_len = ( ack - conn->snd_seq );
572 unsigned int acked_flags = 0;
574 /* Ignore duplicate or out-of-range ACK */
575 if ( ack_len > conn->snd_sent ) {
576 DBGC ( conn, "TCP %p received ACK for [%08lx,%08lx), "
577 "sent only [%08lx,%08lx)\n", conn, conn->snd_seq,
578 ( conn->snd_seq + ack_len ), conn->snd_seq,
579 ( conn->snd_seq + conn->snd_sent ) );
583 /* If we are sending flags and this ACK acknowledges all
584 * outstanding sequence points, then it acknowledges the
585 * flags. (This works since both SYN and FIN will always be
586 * the last outstanding sequence point.)
589 if ( ack_len == conn->snd_sent ) {
590 acked_flags = ( TCP_FLAGS_SENDING ( conn->tcp_state ) &
591 ( TCP_SYN | TCP_FIN ) );
596 /* Update SEQ and sent counters, and window size */
601 /* Stop the retransmission timer */
602 stop_timer ( &conn->timer );
604 /* Notify application of acknowledged data, if any */
605 if ( len && app && app->tcp_op->acked )
606 app->tcp_op->acked ( app, len );
608 /* Mark SYN/FIN as acknowledged if applicable. */
610 conn->tcp_state |= TCP_STATE_ACKED ( acked_flags );
612 /* Notify application of established connection, if applicable */
613 if ( ( acked_flags & TCP_SYN ) &&
614 ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) &&
615 app && app->tcp_op->connected )
616 app->tcp_op->connected ( app );
622 * Handle TCP received data
624 * @v conn TCP connection
625 * @v seq SEQ value (in host-endian order)
626 * @v data Data buffer
627 * @v len Length of data buffer
628 * @ret rc Return status code
630 static int tcp_rx_data ( struct tcp_connection *conn, uint32_t seq,
631 void *data, size_t len ) {
632 struct tcp_application *app = conn->app;
635 /* Ignore duplicate data */
636 already_rcvd = ( conn->rcv_ack - seq );
637 if ( already_rcvd >= len )
639 data += already_rcvd;
642 /* Acknowledge new data */
643 conn->rcv_ack += len;
645 /* Notify application */
646 if ( app && app->tcp_op->newdata )
647 app->tcp_op->newdata ( app, data, len );
653 * Handle TCP received FIN
655 * @v conn TCP connection
656 * @v seq SEQ value (in host-endian order)
657 * @ret rc Return status code
659 static int tcp_rx_fin ( struct tcp_connection *conn, uint32_t seq ) {
660 struct tcp_application *app = conn->app;
662 /* Ignore duplicate FIN */
663 if ( ( conn->rcv_ack - seq ) > 0 )
666 /* Mark FIN as received, acknowledge it, and send our own FIN */
667 conn->tcp_state |= ( TCP_STATE_RCVD ( TCP_FIN ) |
668 TCP_STATE_SENT ( TCP_FIN ) );
671 /* Break association with application */
672 tcp_disassociate ( conn );
674 /* Notify application */
675 if ( app && app->tcp_op->closed )
676 app->tcp_op->closed ( app, 0 );
682 * Handle TCP received RST
684 * @v conn TCP connection
685 * @v seq SEQ value (in host-endian order)
686 * @ret rc Return status code
688 static int tcp_rx_rst ( struct tcp_connection *conn, uint32_t seq ) {
690 /* Accept RST only if it falls within the window. If we have
691 * not yet received a SYN, then we have no window to test
692 * against, so fall back to checking that our SYN has been
695 if ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
696 if ( ( conn->rcv_ack - seq ) > 0 )
699 if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
703 /* Abort connection without sending a RST */
704 tcp_abort ( conn, 0, -ECONNRESET );
710 * Process received packet
712 * @v pkb Packet buffer
713 * @v st_src Partially-filled source address
714 * @v st_dest Partially-filled destination address
715 * @v pshdr_csum Pseudo-header checksum
716 * @ret rc Return status code
718 static int tcp_rx ( struct pk_buff *pkb,
719 struct sockaddr_tcpip *st_src __unused,
720 struct sockaddr_tcpip *st_dest __unused,
721 uint16_t pshdr_csum ) {
722 struct tcp_header *tcphdr = pkb->data;
723 struct tcp_connection *conn;
735 /* Sanity check packet */
736 if ( pkb_len ( pkb ) < sizeof ( *tcphdr ) ) {
737 DBG ( "TCP packet too short at %d bytes (min %d bytes)\n",
738 pkb_len ( pkb ), sizeof ( *tcphdr ) );
742 hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
743 if ( hlen < sizeof ( *tcphdr ) ) {
744 DBG ( "TCP header too short at %d bytes (min %d bytes)\n",
745 hlen, sizeof ( *tcphdr ) );
749 if ( hlen > pkb_len ( pkb ) ) {
750 DBG ( "TCP header too long at %d bytes (max %d bytes)\n",
751 hlen, pkb_len ( pkb ) );
755 csum = tcpip_continue_chksum ( pshdr_csum, pkb->data, pkb_len ( pkb ));
757 DBG ( "TCP checksum incorrect (is %04x including checksum "
758 "field, should be 0000)\n", csum );
763 /* Parse parameters from header and strip header */
764 conn = tcp_demux ( tcphdr->dest );
765 start_seq = seq = ntohl ( tcphdr->seq );
766 ack = ntohl ( tcphdr->ack );
767 win = ntohs ( tcphdr->win );
768 flags = tcphdr->flags;
769 data = pkb_pull ( pkb, hlen );
770 len = pkb_len ( pkb );
773 DBGC ( conn, "TCP %p RX %d<-%d %08lx %08lx..%08lx %4zd",
774 conn, ntohs ( tcphdr->dest ), ntohs ( tcphdr->src ),
775 ntohl ( tcphdr->ack ), ntohl ( tcphdr->seq ),
776 ( ntohl ( tcphdr->seq ) + len +
777 ( ( tcphdr->flags & ( TCP_SYN | TCP_FIN ) ) ? 1 : 0 ) ), len);
778 tcp_dump_flags ( conn, tcphdr->flags );
781 /* If no connection was found, send RST */
783 tcp_send_reset ( conn, tcphdr );
788 /* Handle ACK, if present */
789 if ( flags & TCP_ACK ) {
790 if ( ( rc = tcp_rx_ack ( conn, ack, win ) ) != 0 ) {
791 tcp_send_reset ( conn, tcphdr );
796 /* Handle SYN, if present */
797 if ( flags & TCP_SYN ) {
798 tcp_rx_syn ( conn, seq );
802 /* Handle RST, if present */
803 if ( flags & TCP_RST ) {
804 if ( ( rc = tcp_rx_rst ( conn, seq ) ) != 0 )
808 /* Handle new data, if any */
809 tcp_rx_data ( conn, seq, data, len );
812 /* Handle FIN, if present */
813 if ( flags & TCP_FIN ) {
814 tcp_rx_fin ( conn, seq );
818 /* Dump out any state change as a result of the received packet */
819 tcp_dump_state ( conn );
821 /* Send out any pending data. If peer is expecting an ACK for
822 * this packet then force sending a reply.
824 tcp_senddata_conn ( conn, ( start_seq != seq ) );
826 /* If this packet was the last we expect to receive, set up
827 * timer to expire and cause the connection to be freed.
829 if ( TCP_CLOSED_GRACEFULLY ( conn->tcp_state ) ) {
830 conn->timer.timeout = ( 2 * TCP_MSL );
831 start_timer ( &conn->timer );
836 /* Free received packet */
842 * Bind TCP connection to local port
844 * @v conn TCP connection
845 * @v local_port Local port (in network byte order), or 0
846 * @ret rc Return status code
848 * This function adds the connection to the list of registered TCP
849 * connections. If the local port is 0, the connection is assigned an
850 * available port between 1024 and 65535.
852 static int tcp_bind ( struct tcp_connection *conn, uint16_t local_port ) {
853 struct tcp_connection *existing;
854 static uint16_t try_port = 1024;
856 /* If no port specified, find the first available port */
857 if ( ! local_port ) {
858 for ( ; try_port ; try_port++ ) {
859 if ( try_port < 1024 )
861 if ( tcp_bind ( conn, htons ( try_port ) ) == 0 )
864 DBGC ( conn, "TCP %p could not bind: no free ports\n", conn );
868 /* Attempt bind to local port */
869 list_for_each_entry ( existing, &tcp_conns, list ) {
870 if ( existing->local_port == local_port ) {
871 DBGC ( conn, "TCP %p could not bind: port %d in use\n",
872 conn, ntohs ( local_port ) );
876 conn->local_port = local_port;
878 DBGC ( conn, "TCP %p bound to port %d\n", conn, ntohs ( local_port ) );
883 * Connect to a remote server
885 * @v app TCP application
886 * @v peer Remote socket address
887 * @v local_port Local port number (in network byte order), or 0
888 * @ret rc Return status code
890 * This function initiates a TCP connection to the socket address specified in
891 * peer. It sends a SYN packet to peer. When the connection is established, the
892 * TCP stack calls the connected() callback function.
894 int tcp_connect ( struct tcp_application *app, struct sockaddr_tcpip *peer,
895 uint16_t local_port ) {
896 struct tcp_connection *conn;
899 /* Application must not already have an open connection */
901 DBG ( "TCP app %p already open on %p\n", app, app->conn );
905 /* Allocate connection state storage and add to connection list */
908 DBG ( "TCP app %p could not allocate connection\n", app );
912 /* Bind to peer and to local port */
913 memcpy ( &conn->peer, peer, sizeof ( conn->peer ) );
914 if ( ( rc = tcp_bind ( conn, local_port ) ) != 0 ) {
919 /* Associate with application */
920 tcp_associate ( conn, app );
922 /* Transition to TCP_SYN_SENT and send the SYN */
923 conn->tcp_state = TCP_SYN_SENT;
924 tcp_dump_state ( conn );
925 tcp_senddata_conn ( conn, 0 );
931 * Close the connection
933 * @v app TCP application
935 * The association between the application and the TCP connection is
936 * immediately severed, and the TCP application data structure can be
937 * reused or freed immediately. The TCP connection will persist until
938 * the state machine has returned to the TCP_CLOSED state.
940 void tcp_close ( struct tcp_application *app ) {
941 struct tcp_connection *conn = app->conn;
943 /* If no connection exists, do nothing */
947 /* Break association between application and connection */
948 tcp_disassociate ( conn );
950 /* If we have not yet received a SYN (i.e. we are in CLOSED,
951 * LISTEN or SYN_SENT), just delete the connection
953 if ( ! ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
954 conn->tcp_state = TCP_CLOSED;
955 tcp_dump_state ( conn );
960 /* If we have not had our SYN acknowledged (i.e. we are in
961 * SYN_RCVD), pretend that it has been acknowledged so that we
962 * can send a FIN without breaking things.
964 if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
965 tcp_rx_ack ( conn, ( conn->snd_seq + 1 ), 0 );
967 /* Send a FIN to initiate the close */
968 conn->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
969 tcp_dump_state ( conn );
970 tcp_senddata_conn ( conn, 0 );
974 struct tcpip_protocol tcp_protocol __tcpip_protocol = {
977 .tcpip_proto = IP_TCP,