BA / Mbed OS BaBoRo1
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp.c Source File

tcp.c

00001 /*
00002  * Copyright (c) 2013-2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "nsconfig.h"
00019 #include "string.h"
00020 #include "ns_types.h"
00021 #include "ns_trace.h"
00022 #include "eventOS_event.h"
00023 #include "Core/include/socket.h"
00024 #include "nsdynmemLIB.h"
00025 #include "ip_fsc.h"
00026 #include "ns_sha256.h"
00027 #include "NWK_INTERFACE/Include/protocol.h"
00028 #include "NWK_INTERFACE/Include/protocol_timer.h"
00029 #include "randLIB.h"
00030 #include "Common_Protocols/ipv6_constants.h"
00031 #include "Common_Protocols/ipv6_flow.h"
00032 #include "Common_Protocols/tcp.h"
00033 #include "NWK_INTERFACE/Include/protocol_stats.h"
00034 #include "common_functions.h"
00035 #include "net_interface.h"
00036 
00037 #ifndef NO_TCP
00038 #define TRACE_GROUP "tcp"
00039 
00040 /* Standard flags for outgoing packets in each state, with FIN applying
00041  * only if there is no more data in queue (because the state is entered
00042  * while queue not empty).
00043  */
00044 static const uint8_t state_flag[TCP_STATES] =
00045 {
00046     [TCP_STATE_CLOSED] = TCP_FLAG_RST | TCP_FLAG_ACK,
00047     [TCP_STATE_SYN_SENT] = TCP_FLAG_SYN,
00048     [TCP_STATE_SYN_RECEIVED] = TCP_FLAG_SYN | TCP_FLAG_ACK,
00049     [TCP_STATE_ESTABLISHED] = TCP_FLAG_ACK,
00050     [TCP_STATE_FIN_WAIT_1] = TCP_FLAG_FIN | TCP_FLAG_ACK,
00051     [TCP_STATE_FIN_WAIT_2] = TCP_FLAG_ACK,
00052     [TCP_STATE_CLOSE_WAIT] = TCP_FLAG_ACK,
00053     [TCP_STATE_LAST_ACK] = TCP_FLAG_FIN | TCP_FLAG_ACK,
00054     [TCP_STATE_CLOSING] = TCP_FLAG_FIN | TCP_FLAG_ACK,
00055     [TCP_STATE_TIME_WAIT] = TCP_FLAG_ACK
00056 };
00057 
00058 #ifdef TCP_TEST
00059 static uint8_t rx_drops[TCP_STATES];
00060 static uint8_t tx_drops[TCP_STATES];
00061 
00062 /*Test - functions*/
00063 int8_t tcp_test_drop_tx(int state, uint8_t count) {
00064 
00065     tx_drops[state] = count;
00066     return 0;
00067 }
00068 
00069 int8_t tcp_test_drop_rx(int state, uint8_t count) {
00070 
00071     rx_drops[state] = count;
00072     return 0;
00073 }
00074 
00075 void tcp_test_drop_reset() {
00076 
00077   memset(rx_drops, 0, sizeof rx_drops);
00078   memset(tx_drops, 0, sizeof tx_drops);
00079 
00080 }
00081 #endif
00082 
00083 #ifdef FEA_TRACE_SUPPORT
00084 static const char *trace_tcp_flags(uint16_t flags)
00085 {
00086     static char buf[9];
00087     buf[0] = flags & TCP_FLAG_CWR ? 'C' : '-';
00088     buf[1] = flags & TCP_FLAG_ECE ? 'E' : '-';
00089     buf[2] = flags & TCP_FLAG_URG ? 'U' : '-';
00090     buf[3] = flags & TCP_FLAG_ACK ? 'A' : '-';
00091     buf[4] = flags & TCP_FLAG_PSH ? 'P' : '-';
00092     buf[5] = flags & TCP_FLAG_RST ? 'R' : '-';
00093     buf[6] = flags & TCP_FLAG_SYN ? 'S' : '-';
00094     buf[7] = flags & TCP_FLAG_FIN ? 'F' : '-';
00095     return buf;
00096 }
00097 #endif
00098 
00099 static void tcp_timer_handle(uint16_t ticksUpdate);
00100 static void tcp_segment_start(tcp_session_t *tcp_info, bool timeout);
00101 static void tcp_uack_segment(buffer_t *buf, tcp_session_t *tcp_info, uint16_t header_length);
00102 static buffer_t *tcp_ack_buffer(tcp_session_t *tcp_info, uint16_t new_ack);
00103 static void tcp_ack_segment(uint32_t ack, tcp_session_t *tcp_info);
00104 static buffer_t *tcp_build_reset_packet(const sockaddr_t *dst_addr, const sockaddr_t *src_addr, uint32_t seq, uint32_t ack, uint8_t flag);
00105 static void tcp_session_established(protocol_interface_info_entry_t *cur, tcp_session_t *tcp_info);
00106 static void tcp_build(buffer_t *buf, tcp_session_t *tcp_info);
00107 
00108 static uint16_t tcp_session_count;
00109 
00110 #define TCP_FUNC_ENTRY_TRACE
00111 #ifdef TCP_FUNC_ENTRY_TRACE
00112 #define FUNC_ENTRY_TRACE    tr_debug
00113 #else
00114 #define FUNC_ENTRY_TRACE(...)
00115 #endif
00116 
00117 /* Returns true if min <= val <= max */
00118 static bool tcp_seq_in_range(uint32_t min, uint32_t val, uint32_t max)
00119 {
00120     if (min <= max) {
00121         return min <= val && val <= max;
00122     } else {
00123         return min <= val || val <= max;
00124     }
00125 }
00126 /* Returns true if val > low */
00127 static bool tcp_seq_gt(uint32_t val, uint32_t low)
00128 {
00129     return common_serial_number_greater_32(val, low);
00130 }
00131 
00132 /* Returns true if val < high */
00133 static bool tcp_seq_lt(uint32_t val, uint32_t high)
00134 {
00135     return common_serial_number_greater_32(high, val);
00136 }
00137 
00138 /* Returns true if val >= min */
00139 static bool tcp_seq_ge(uint32_t val, uint32_t min)
00140 {
00141     return val == min || common_serial_number_greater_32(val, min);
00142 }
00143 
00144 #if 0
00145 /* Returns true if val <= max */
00146 static bool tcp_seq_le(uint32_t val, uint32_t max)
00147 {
00148     return val == max || common_serial_number_greater_32(max, val);
00149 }
00150 #endif
00151 
00152 /* Delete TCP session (optionally with error) */
00153 static tcp_session_t *tcp_session_delete_with_error(tcp_session_t *tcp_info, uint8_t error)
00154 {
00155     socket_t *socket = tcp_info->inet_pcb ->socket;
00156     FUNC_ENTRY_TRACE("tcp_session_delete_with_error(), s=%d", socket->id );
00157     socket_connection_abandoned(socket, tcp_info->interface->id , error);
00158     return tcp_session_ptr_free(tcp_info);
00159 }
00160 
00161 static tcp_session_t *tcp_session_delete(tcp_session_t *tcp_info)
00162 {
00163     return tcp_session_delete_with_error(tcp_info, 0);
00164 }
00165 
00166 /* Socket released by application */
00167 void tcp_socket_released(tcp_session_t *cur)
00168 {
00169     FUNC_ENTRY_TRACE("tcp_socket_released() s=%d", cur->inet_pcb->socket->id);
00170 
00171     /* Most clear-up already done, including tcp_session_close */
00172 
00173     /* Only thing to do is start "orphaned session" timer for FIN-WAIT-2 */
00174 
00175     if (cur->state == TCP_STATE_FIN_WAIT_2) {
00176         cur->timer = TCP_FIN_WAIT_2_TIMEOUT;
00177     }
00178 }
00179 
00180 /* RFC 6528 Initial Sequence Number generation */
00181 static uint32_t tcp_generate_isn(const uint8_t local_ip[static 16], uint16_t local_port,
00182                                  const uint8_t remote_ip[static 16], uint16_t remote_port)
00183 {
00184     static struct {
00185         uint8_t key[16];
00186         bool initialised;
00187     } secret;
00188     static uint32_t fudge;
00189 
00190     tr_debug("isn [%s]:%u -> [%s]:%u", trace_ipv6(local_ip), local_port, trace_ipv6(remote_ip), remote_port);
00191 
00192     if (!secret.initialised) {
00193         /* randLIB should do - we're not after total cryptographic security, and
00194          * it should have been seeded from true randomness. An alternative would
00195          * be the secret given to addr_opaque_iid_key_set, but that would have
00196          * the effect of restarting with the same ISN after reboot. Random secret
00197          * means we start with a random ISN after reboot.
00198          */
00199         randLIB_get_n_bytes_random(secret.key, sizeof secret.key);
00200         secret.initialised = true;
00201         tr_debug("secret init");
00202     }
00203 
00204     ns_sha256_context ctx;
00205     uint32_t F;
00206     ns_sha256_init(&ctx);
00207     ns_sha256_starts(&ctx);
00208     ns_sha256_update(&ctx, local_ip, 16);
00209     ns_sha256_update(&ctx, &local_port, sizeof local_port);
00210     ns_sha256_update(&ctx, remote_ip, 16);
00211     ns_sha256_update(&ctx, &remote_port, sizeof remote_port);
00212     ns_sha256_update(&ctx, secret.key, sizeof secret.key);
00213     ns_sha256_finish_nbits(&ctx, &F, 32);
00214     ns_sha256_free(&ctx);
00215 
00216     /* Want to make sure we're always going up in successive connects, so
00217      * add a positive fraction of a tick every time.
00218      */
00219     fudge += randLIB_get_8bit() + 1;
00220 
00221     /* Monotonic time is 100ms ticks, so *25000 converts to 4us ticks */
00222     uint32_t M = 25000 * protocol_core_monotonic_time + fudge;
00223     tr_debug("ISN=%"PRIx32" M=%"PRIx32" F=%"PRIx32" fudge=%"PRIx32, M + F, M, F, fudge);
00224 
00225     return M + F;
00226 }
00227 
00228 static void tcp_set_metadata(const inet_pcb_t *inet_pcb, buffer_t *buf)
00229 {
00230     /* Fill in metadata from inet_pcb. Everything used here should be cloned into
00231      * new PCBs created by incoming connections from the listening PCB, so that it's
00232      * possible to set options for the first transactions prior to accept().
00233      */
00234     buf->options .traffic_class  = inet_pcb->tclass;
00235     buf->options .flow_label  = inet_pcb->flow_label;
00236     buf->options .ll_security_bypass_tx  = (inet_pcb->link_layer_security == 0);
00237     buf->options .ipv6_dontfrag  = true; // Sanity-checking - if doing MTU work right, fragmentation should never be needed
00238     socket_inet_pcb_set_buffer_hop_limit(inet_pcb, buf, NULL);
00239 }
00240 
00241 static void tcp_rethink_mss(tcp_session_t *tcp_info)
00242 {
00243     tcp_info->send_mss_eff = tcp_info->send_mss_peer;
00244     if (tcp_info->interface->nwk_id == IF_6LoWPAN) {
00245         // This conservatism also covers up worries about extension headers,
00246         // RPL tunnelling...
00247         if (tcp_info->send_mss_eff > TCP_LOWPAN_MSS_LIMIT) {
00248             tcp_info->send_mss_eff = TCP_LOWPAN_MSS_LIMIT;
00249         }
00250     }
00251     /* No proper PMTUD at the minute... */
00252     if (tcp_info->send_mss_eff > IPV6_MIN_LINK_MTU - 20 - 40) {
00253         tcp_info->send_mss_eff = IPV6_MIN_LINK_MTU - 20 - 40;
00254     }
00255 
00256     /* Don't get totally silly */
00257     if (tcp_info->send_mss_eff < 64) {
00258         tcp_info->send_mss_eff = 64;
00259     }
00260 }
00261 
00262 /* Allocate new TCP socket data structure */
00263 tcp_session_t *tcp_session_ptr_allocate(inet_pcb_t *inet_pcb, tcp_session_t *from_time_wait)
00264 {
00265     tcp_session_t *cur = NULL;
00266     FUNC_ENTRY_TRACE("tcp_session_ptr_allocate() s=%d", inet_pcb->socket->id );
00267 
00268     cur = ns_dyn_mem_alloc(sizeof(tcp_session_t));
00269     if (cur) {
00270         if (++tcp_session_count == 1) {
00271             protocol_timer_start(PROTOCOL_TIMER_TCP_TIM, tcp_timer_handle, TCP_TIMER_PERIOD);
00272         }
00273         cur->passive_open = false;
00274         cur->interface = 0;
00275         cur->busy = false;
00276         cur->persist = false;
00277         cur->sent_fin = false;
00278         cur->receive_next = 0;
00279         cur->receive_adv = 0;
00280         cur->send_window = 0;
00281         if (from_time_wait) {
00282             cur->send_next = from_time_wait->send_next + UINT32_C(250000) + randLIB_get_16bit();
00283             tcp_session_delete(from_time_wait);
00284         } else {
00285             cur->send_next = tcp_generate_isn(inet_pcb->local_address , inet_pcb->local_port , inet_pcb->remote_address , inet_pcb->remote_port );
00286         }
00287         cur->send_unacknowledged = cur->send_next;
00288         cur->state = TCP_STATE_CLOSED;
00289         cur->timer = 0;
00290         cur->retry = 0;
00291         cur->inet_pcb = inet_pcb;
00292         cur->srtt8 = INT16_MAX; // indicates no sample yet
00293         cur->srttvar4 = INT16_MAX;
00294         cur->rto = TCP_INITIAL_RTO;
00295         cur->receive_mss = IPV6_MIN_LINK_MTU - 20 - 40;
00296         cur->send_mss_eff = 536;
00297         cur->send_mss_peer = 536;
00298         inet_pcb->session  = cur;
00299         socket_reference(inet_pcb->socket);
00300     }
00301     return cur;
00302 }
00303 
00304 /* Free TCP session pointer */
00305 tcp_session_t *tcp_session_ptr_free(tcp_session_t *tcp_info)
00306 {
00307     socket_t *so = tcp_info->inet_pcb ->socket;
00308     FUNC_ENTRY_TRACE("tcp_session_ptr_free() s=%d", so->id );
00309     tcp_info->inet_pcb->session = NULL;
00310     so->flags  |= SOCKET_FLAG_CANT_RECV_MORE | SOCKET_FLAG_SHUT_WR;
00311     // This could free both the inet PCB and the socket - do not reference further
00312     socket_dereference(so);
00313     tcp_info->inet_pcb = NULL;
00314 
00315     ns_dyn_mem_free(tcp_info);
00316 
00317     if (--tcp_session_count == 0) {
00318         protocol_timer_stop(PROTOCOL_TIMER_TCP_TIM);
00319     }
00320 
00321     return NULL;
00322 }
00323 
00324 tcp_error tcp_session_send(tcp_session_t *tcp_info, buffer_t *buf)
00325 {
00326     FUNC_ENTRY_TRACE("tcp_session_send()");
00327 
00328     if (tcp_info->state != TCP_STATE_ESTABLISHED && tcp_info->state != TCP_STATE_CLOSE_WAIT) {
00329         tr_error("tcp error, bad state %d", tcp_info->state);
00330         return TCP_ERROR_WRONG_STATE;
00331     }
00332 
00333     /* Wipe out the socket ID - never having socket ID set on down buffers ensures no callbacks are generated by core layers */
00334     buffer_socket_set(buf, NULL);
00335     buf->session_ptr = NULL;
00336     sockbuf_append_and_compress(&tcp_info->inet_pcb->socket->sndq, buf);
00337 
00338     if (!tcp_info->busy) {
00339         tcp_info->timer = 0;
00340         tcp_info->retry = 0;
00341         tcp_info->busy = true;
00342         tcp_segment_start(tcp_info, false);
00343     }
00344 
00345     return TCP_ERROR_NO_ERROR;
00346 }
00347 
00348 
00349 /* Builds and returns a RST packet; frees incoming buffer;
00350  * if session is provided, deletes session and signals error to user
00351  */
00352 static buffer_t *tcp_reset_response(tcp_session_t *tcp_info, uint8_t error, buffer_t *incoming_buf, uint32_t seq, uint32_t ack, uint8_t flags)
00353 {
00354     FUNC_ENTRY_TRACE("tcp_reset_response()");
00355     buffer_t *rst_buffer;
00356 
00357     rst_buffer = tcp_build_reset_packet(&incoming_buf->src_sa , &incoming_buf->dst_sa , seq, ack, flags);
00358     if (rst_buffer) {
00359         rst_buffer->interface  = incoming_buf->interface ;
00360         if (tcp_info) {
00361             tcp_set_metadata(tcp_info->inet_pcb, rst_buffer);
00362         }
00363     }
00364     buffer_free(incoming_buf);
00365     if (tcp_info) {
00366         tcp_session_delete_with_error(tcp_info, error);
00367     }
00368 
00369     return (rst_buffer);
00370 }
00371 
00372 static buffer_t *tcp_build_reset_packet(const sockaddr_t *dst_addr, const sockaddr_t *src_addr, uint32_t seq, uint32_t ack, uint8_t flags)
00373 {
00374     buffer_t *buf;
00375     uint8_t *ptr;
00376 
00377     FUNC_ENTRY_TRACE("tcp_build_reset_packet()");
00378     buf = buffer_get(20);
00379 
00380     if (!buf) {
00381         return NULL;
00382     }
00383 
00384     buf->dst_sa  = *dst_addr;
00385     buf->src_sa  = *src_addr;
00386     buf->info  = (buffer_info_t)(B_DIR_DOWN | B_FROM_TCP | B_TO_IPV6);
00387     buf->options .type  = IPV6_NH_TCP;
00388 
00389     ptr = buffer_data_pointer(buf);
00390     ptr = common_write_16_bit(src_addr->port , ptr);
00391     ptr = common_write_16_bit(dst_addr->port , ptr);
00392     ptr = common_write_32_bit(seq, ptr);
00393     ptr = common_write_32_bit(ack, ptr);
00394     *ptr++ = 5 << 4; /* data offset */
00395     *ptr++ = flags;
00396     ptr = common_write_16_bit(0, ptr);
00397     ptr = common_write_32_bit(0, ptr); /* checksum and URG pointer */
00398     buffer_data_end_set(buf, ptr);
00399 
00400     /* calculate checksum */
00401     common_write_16_bit(buffer_ipv6_fcf(buf, IPV6_NH_TCP), buffer_data_pointer(buf) + 16);
00402 
00403     return (buf);
00404 }
00405 
00406 static void tcp_session_send_reset_to_abort_connection(tcp_session_t *tcp_info) {
00407 
00408     sockaddr_t dst, src;
00409     memcpy(&dst.address , tcp_info->inet_pcb->remote_address, 16);
00410     memcpy(&src.address , tcp_info->inet_pcb->local_address, 16);
00411     dst.addr_type  = ADDR_IPV6 ;
00412     src.addr_type  = ADDR_IPV6 ;
00413     dst.port  = tcp_info->inet_pcb->remote_port;
00414     src.port  = tcp_info->inet_pcb->local_port;
00415     buffer_t *buf = tcp_build_reset_packet(&dst, &src, tcp_info->send_next, 0, TCP_FLAG_RST);
00416     if (!buf) {
00417         return;
00418     }
00419 
00420     buf->interface  = tcp_info->interface;
00421     tcp_set_metadata(tcp_info->inet_pcb, buf);
00422     /* Don't fill in socket ID, or app would get a TX DONE callback for this */
00423     protocol_push(buf);
00424 }
00425 
00426 /**
00427  * \brief Function used for starting a TCP connection
00428  * to a remote server.
00429  *
00430  * \param tcp_session pointer to allocated tcp session
00431  * \param dst_address_ptr pointer to connection dstination address
00432  * \param dst_port connection destination port
00433  *
00434  * \return TCP_ERROR_NO_ERROR
00435  * \return TCP_ERROR_BUFFER_ALLOCATION_ERROR
00436  */
00437 
00438 tcp_error tcp_session_open(tcp_session_t *tcp_session)
00439 {
00440     buffer_t *new_buffer;
00441     protocol_interface_info_entry_t *cur_interface;
00442     FUNC_ENTRY_TRACE("tcp_session_open()");
00443 
00444     if (tcp_session->state != TCP_STATE_CLOSED && tcp_session->state != TCP_STATE_LISTEN) {
00445         return TCP_ERROR_WRONG_STATE;
00446     }
00447 
00448     new_buffer = buffer_get(127);
00449     if (!new_buffer) {
00450         return TCP_ERROR_BUFFER_ALLOCATION_ERROR;
00451     }
00452 
00453     new_buffer->dst_sa .port  = tcp_session->inet_pcb->remote_port;
00454     new_buffer->dst_sa .addr_type  = ADDR_IPV6 ;
00455     memcpy(new_buffer->dst_sa .address , tcp_session->inet_pcb->remote_address, 16);
00456 
00457     cur_interface = socket_interface_determine(tcp_session->inet_pcb->socket, new_buffer);
00458 
00459     if (!cur_interface) {
00460         buffer_free(new_buffer);
00461         return TCP_ERROR_BUFFER_ALLOCATION_ERROR;
00462     }
00463 
00464     /**
00465      * Save interface id and type
00466      */
00467     new_buffer->interface  = cur_interface;
00468     tcp_session->interface = cur_interface;
00469 
00470     new_buffer->interface ->id = cur_interface->id;
00471     tcp_session->interface->id = cur_interface->id;
00472 
00473     if (tcp_session->interface->nwk_id == IF_6LoWPAN) {
00474         if (tcp_session->receive_mss > TCP_LOWPAN_MSS_LIMIT) {
00475             tcp_session->receive_mss = TCP_LOWPAN_MSS_LIMIT;
00476         }
00477     }
00478 
00479     tcp_session->state = TCP_STATE_SYN_SENT;
00480     new_buffer->options .code  = TCP_FLAG_SYN;
00481 
00482     tcp_build(new_buffer, tcp_session);
00483     return TCP_ERROR_NO_ERROR;
00484 
00485 }
00486 
00487 tcp_error tcp_session_shutdown_read(tcp_session_t *tcp_session)
00488 {
00489     FUNC_ENTRY_TRACE("tcp_session_shutdown_read");
00490 
00491     if (tcp_session->inet_pcb->socket->rcvq.data_bytes != 0) {
00492         // Force a reset shutdown (RFC 1122 4.2.2.13, RFC 2525 2.17)
00493         tr_warn("Shutdown read with pending data");
00494         return tcp_session_abort(tcp_session);
00495     }
00496 
00497     return TCP_ERROR_NO_ERROR;
00498 }
00499 
00500 /**
00501  * \brief Function used for closing a TCP connection.
00502  *
00503  * If it returns TCP_ERROR_NO_ERROR, TCP session is persisting.
00504  * Any error return means TCP session has been deleted.
00505  *
00506  * \param tcp_session pointer to indicate tcp session
00507  *
00508  * \return TCP_ERROR_NO_ERROR
00509  * \return TCP_ERROR_BUFFER_ALLOCATION_ERROR
00510  */
00511 
00512 tcp_error tcp_session_close(tcp_session_t *tcp_session)
00513 {
00514     FUNC_ENTRY_TRACE("tcp_session_close");
00515     switch (tcp_session->state) {
00516         case TCP_STATE_CLOSED:
00517         case TCP_STATE_LAST_ACK:
00518         case TCP_STATE_FIN_WAIT_1:
00519         case TCP_STATE_FIN_WAIT_2:
00520         case TCP_STATE_CLOSING:
00521         case TCP_STATE_TIME_WAIT:
00522             return TCP_ERROR_NO_ERROR;
00523         case TCP_STATE_LISTEN:
00524         case TCP_STATE_SYN_SENT:
00525         default:
00526             tcp_session_delete(tcp_session);
00527             return TCP_SESSION_REMOVED;
00528         case TCP_STATE_SYN_RECEIVED:
00529         case TCP_STATE_ESTABLISHED:
00530         case TCP_STATE_CLOSE_WAIT:
00531             // Do the state change immediately, even if data
00532             // pending - this deals with the API changes. Data
00533             // output routines need to set flags appropriately.
00534             if (tcp_session->state == TCP_STATE_CLOSE_WAIT) {
00535                 tcp_session->state = TCP_STATE_LAST_ACK; // RFC 1122
00536                 tr_debug("sLA");
00537             } else {
00538                 tcp_session->state = TCP_STATE_FIN_WAIT_1;
00539                 tr_debug("sFW");
00540             }
00541             if (!tcp_session->busy) {
00542                 tcp_session->busy = true;
00543                 tcp_segment_start(tcp_session, false);
00544             }
00545             return TCP_ERROR_NO_ERROR;
00546     }
00547 }
00548 
00549 tcp_error tcp_session_abort(tcp_session_t *tcp_session)
00550 {
00551     FUNC_ENTRY_TRACE("tcp_session_abort");
00552 
00553     switch (tcp_session->state) {
00554         case TCP_STATE_CLOSED:
00555             return TCP_ERROR_SOCKET_NOT_FOUND;
00556         case TCP_STATE_SYN_RECEIVED:
00557         case TCP_STATE_ESTABLISHED:
00558         case TCP_STATE_FIN_WAIT_1:
00559         case TCP_STATE_FIN_WAIT_2:
00560         case TCP_STATE_CLOSE_WAIT:
00561             tcp_session_send_reset_to_abort_connection(tcp_session);
00562             /* no break */
00563         case TCP_STATE_LISTEN:
00564         case TCP_STATE_SYN_SENT:
00565             tcp_session_delete_with_error(tcp_session, SOCKET_CONNECTION_RESET);
00566             return TCP_ERROR_NO_ERROR;
00567         default:
00568             tcp_session_delete(tcp_session);
00569             return TCP_ERROR_NO_ERROR;
00570     }
00571 }
00572 
00573 /**
00574  * \brief Function used to send TCP message
00575  *
00576  * Can be either used to send a data segment or FIN in case there
00577  * is no data. When retransmission is made, starts to sent from the
00578  * start of the unacknowledged data.
00579  *
00580  * \param tcp_info pointer to indicate tcp session
00581  * \param timeout triggered from timeout
00582  *
00583  * \return TCP_ERROR_NO_ERROR
00584  * \return TCP_ERROR_BUFFER_ALLOCATION_ERROR
00585  */
00586 static void tcp_segment_start(tcp_session_t *tcp_info, bool timeout)
00587 {
00588     socket_t *so = tcp_info->inet_pcb ->socket;
00589     buffer_t *tx_data = ns_list_get_first(&so->sndq.bufs);
00590     buffer_t *buf;
00591 
00592     FUNC_ENTRY_TRACE("tcp_segment_start() s=%d", so->id );
00593 
00594     if (timeout) {
00595         // If not same means that retransmission is made. Could be either
00596         // partial or full depending on what has been acknowledged. If data
00597         // is to be sent, sends always window size
00598         tcp_info->send_next = tcp_info->send_unacknowledged;
00599         tcp_info->sent_fin = false;
00600     }
00601 
00602     uint16_t data_length;
00603 
00604     if (!tx_data) {
00605         // Should only be called with no data if needing to send a SYN or FIN
00606         if ((state_flag[tcp_info->state] & TCP_FLAG_SYN) ||
00607             ((state_flag[tcp_info->state] & TCP_FLAG_FIN) && !tcp_info->sent_fin)) {
00608             data_length = 0;
00609             tcp_info->persist = false;
00610             goto build;
00611         } else {
00612             tr_warn("unexpected tcp_segment_start");
00613             return;
00614         }
00615     }
00616 
00617     data_length = buffer_data_length(tx_data);
00618     if (data_length > tcp_info->send_mss_eff) {
00619         data_length = tcp_info->send_mss_eff;
00620     }
00621     /* Can transmit up to SND.UNA+SND.WND-1 */
00622     /* Simplified by SND.UNA==SND.NXT */
00623     if (data_length > tcp_info->send_window) {
00624         data_length = tcp_info->send_window;
00625     }
00626 
00627     if (data_length == 0) {
00628         if (!timeout) {
00629             /* Start timer for probe */
00630             tcp_info->persist = true;
00631             tcp_info->timer = tcp_info->rto;
00632             tcp_info->retry = 0;
00633             return;
00634         } else {
00635             // Think - why actually 1? Given we don't resegmentise, and end
00636             // up committed to sending a 1-byte segment in this situation, may
00637             // as well just go for send_mss_eff or 64 for our probe. No rule
00638             // against it.
00639             data_length = 1;
00640         }
00641     } else {
00642         tcp_info->persist = false;
00643     }
00644 
00645 build:
00646     /* Create buffer for message */
00647     buf = buffer_get(data_length);
00648     if (buf == NULL) {
00649         goto out;
00650     }
00651 
00652     buf->dst_sa .port  = tcp_info->inet_pcb->remote_port;
00653     buf->dst_sa .addr_type  = ADDR_IPV6 ;
00654     memcpy(buf->dst_sa .address , tcp_info->inet_pcb->remote_address, 16);
00655     buf->src_sa .port  = tcp_info->inet_pcb->local_port;
00656     buf->src_sa .addr_type  = ADDR_IPV6 ;
00657     memcpy(buf->src_sa .address , tcp_info->inet_pcb->local_address, 16);
00658 
00659     // Add data to message buffer, but do not remove it from socket buffer until
00660     // it is acked
00661     if (tx_data) {
00662         buffer_data_add(buf, buffer_data_pointer(tx_data), data_length);
00663     }
00664 
00665     buf->interface  = tcp_info->interface;
00666 
00667     tcp_build(buf, tcp_info);
00668 out:
00669     /* Start retransmit timer (also covers buffer failure) */
00670     tcp_info->timer = tcp_info->rto;
00671 }
00672 
00673 
00674 /**
00675  * \brief Function used for resenting segment after timeout.
00676  *
00677  * \param tcp_info identifies the connection
00678  */
00679 
00680 static tcp_session_t *tcp_resend_segment(tcp_session_t *tcp_info)
00681 {
00682     FUNC_ENTRY_TRACE("tcp_resend_segment()");
00683 
00684     if (tcp_info->retry >= (tcp_info->state < TCP_STATE_ESTABLISHED ? TCP_SYN_RETRIES : TCP_MAX_RETRIES)) {
00685         tr_debug("Too many retries");
00686         return tcp_session_delete_with_error(tcp_info, SOCKET_TX_FAIL);
00687     }
00688 
00689     if (++tcp_info->retry == TCP_PROBLEM_RETRIES) {
00690         socket_event_push(SOCKET_CONNECTION_PROBLEM, tcp_info->inet_pcb->socket, tcp_info->interface->id, NULL, 0);
00691         ipv6_neighbour_reachability_problem(tcp_info->inet_pcb->remote_address, tcp_info->interface->id);
00692     }
00693 
00694     tcp_segment_start(tcp_info, true);
00695 
00696     tr_debug("RE-TX, timer %d", tcp_info->timer);
00697     return tcp_info;
00698 }
00699 
00700 static uint16_t tcp_compute_window_incr(tcp_session_t *tcp_info)
00701 {
00702     // Careful window adjustment (RFC 1122 et al) - don't move right edge
00703     // leftwards, and don't jump up in small steps
00704     int32_t window = sockbuf_space(&tcp_info->inet_pcb->socket->rcvq);
00705     if (window < 0) {
00706         window = 0;
00707     }
00708     if (window > 0xffff) {
00709         window = 0xffff;
00710     }
00711     if (window < (int32_t) (tcp_info->receive_adv - tcp_info->receive_next)) {
00712         // Don't move left
00713         return 0;
00714     }
00715 
00716     // Don't make small increments (avoid Silly Window Syndrome)
00717     uint16_t incr = tcp_info->receive_next + window - tcp_info->receive_adv;
00718     if (incr > 0) {
00719         if (incr < tcp_info->inet_pcb->socket->rcvq.data_byte_limit / 2 &&
00720             incr < tcp_info->send_mss_eff) {
00721             incr = 0;
00722         } else {
00723             tcp_info->receive_adv += incr;
00724         }
00725     }
00726 
00727     return incr;
00728 }
00729 
00730 void tcp_session_data_received(tcp_session_t *tcp_info)
00731 {
00732     // If this read nudges up the window, send an ack
00733     // Layering all a little wonky here, but this should roughly work.
00734     // Revisit when delayed ack infrastructure in place.
00735     if (tcp_compute_window_incr(tcp_info)) {
00736         buffer_t *buf = tcp_ack_buffer(tcp_info, 0);
00737         tcp_build(buf, tcp_info);
00738     }
00739 }
00740 
00741 /**
00742  * \brief Function used for allocating buffer for ack segment.
00743  *
00744  * \param tcp_info identifies the connection
00745  * \param new_ack new bytes to be acknowledged
00746  *
00747  * \return allocated buffer on success
00748  * \return 0 pointer indicates an error
00749  */
00750 
00751 static buffer_t *tcp_ack_buffer(tcp_session_t *tcp_info, uint16_t new_ack)
00752 {
00753     /* make ack segment */
00754 
00755     buffer_t *new_buffer;
00756     FUNC_ENTRY_TRACE("tcp_ack_buffer() s=%d, new_ack=%d", tcp_info->inet_pcb->socket->id, new_ack);
00757 
00758     new_buffer = buffer_get(0);
00759     if (!new_buffer) {
00760         return NULL;
00761     }
00762 
00763     new_buffer->dst_sa .port  = tcp_info->inet_pcb->remote_port;
00764     new_buffer->dst_sa .addr_type  = ADDR_IPV6 ;
00765     memcpy(new_buffer->dst_sa .address , tcp_info->inet_pcb->remote_address, 16);
00766     new_buffer->src_sa .port  = tcp_info->inet_pcb->local_port;
00767     new_buffer->src_sa .addr_type  = ADDR_IPV6 ;
00768     memcpy(new_buffer->src_sa .address , tcp_info->inet_pcb->local_address, 16);
00769 
00770     new_buffer->interface  = tcp_info->interface;
00771     new_buffer->info  = (buffer_info_t)(B_DIR_DOWN | B_FROM_TCP);
00772     new_buffer->options .code  = 0xff;
00773     tcp_info->receive_next += new_ack;
00774 
00775     return new_buffer;
00776 }
00777 
00778 /**
00779  * \brief Function used for saving segments needing to be acknowledged.
00780  *
00781  * \param buf buffer to be acknowledged
00782  * \param tcp_info identifies the connection
00783  */
00784 
00785 static void tcp_uack_segment(buffer_t *buf, tcp_session_t *tcp_info, uint16_t header_length)
00786 {
00787     FUNC_ENTRY_TRACE("tcp_uack_segment() s=%d", tcp_info->inet_pcb->socket->id);
00788 
00789     uint16_t seg_size = buffer_data_length(buf) - header_length;
00790     if (buf->options .code  & TCP_FLAG_SYN) {
00791         seg_size++;
00792     }
00793     if (buf->options .code  & TCP_FLAG_FIN) {
00794         seg_size++;
00795         if (tcp_info->sent_fin) {
00796             tr_err("sent 2 FINs");
00797         }
00798         tcp_info->sent_fin = true;
00799     }
00800 
00801     if (seg_size == 0) {
00802         return;
00803     }
00804 
00805     tcp_info->send_next += seg_size;
00806     if (tcp_info->timer == 0) {
00807         tcp_info->timer = tcp_info->rto;
00808     }
00809 
00810     tcp_info->busy = true;
00811 }
00812 
00813 
00814 /**
00815  * \brief Peer has acknowledged data.
00816  *
00817  * \param ack sequence being acknowledged
00818  * \param tcp_info identifies the connection
00819  *
00820  */
00821 
00822 static void tcp_ack_segment(uint32_t ack, tcp_session_t *tcp_info)
00823 {
00824     FUNC_ENTRY_TRACE("tcp_ack_segment() s=%d", (int)tcp_info->inet_pcb->socket->id);
00825 
00826     socket_t *so = tcp_info->inet_pcb ->socket;
00827 
00828     uint32_t acked_bytes;
00829     acked_bytes = ack - tcp_info->send_unacknowledged;
00830 
00831     tr_debug("tcp_ack_segment() acked %"PRIu32, acked_bytes);
00832 
00833     // Do not allow to remove more than sent data from buffer
00834     if (acked_bytes > so->sndq.data_bytes) {
00835         acked_bytes = so->sndq.data_bytes;
00836     }
00837     sockbuf_drop(&so->sndq, acked_bytes);
00838     tr_debug("tcp_ack_segment() socket remove from buffer %"PRIu32" data to be sent %"PRIu32, acked_bytes, so->sndq.data_bytes);
00839 
00840     tcp_info->send_unacknowledged = ack;
00841 
00842     ipv6_neighbour_reachability_confirmation(tcp_info->inet_pcb->remote_address, tcp_info->interface->id);
00843 
00844     uint32_t remaining_bytes = so->sndq.data_bytes;
00845 
00846     if (tcp_info->state >= TCP_STATE_ESTABLISHED) {
00847         // Could consider not sending event if space below low water?
00848         socket_event_push(SOCKET_TX_DONE, so, tcp_info->interface->id , tcp_info, remaining_bytes);
00849     }
00850 
00851     // All data that has been send is acked so sent next segment
00852     if (ack == tcp_info->send_next) {
00853 
00854         // Made when all data has been acked
00855         // Could do this only periodically, based on a timer, for speed
00856         // Or, as RFC 4861 suggests, once per RTT. Which RTO calculation is,
00857         // so keep this with the RTO recalculation code.
00858         if (tcp_info->retry == 0 && !tcp_info->persist) {
00859             /* Update RTT - RFC 6298, using tricks in Van Jacoben's 1988 paper */
00860             /* Most variables held as scaled 16-bit positive signed integers */
00861             int16_t R = (int16_t) tcp_info->rto - (int16_t)tcp_info->timer;
00862             if (R < 0) {
00863                 tr_err("R=%"PRId16, R);
00864                 R = 0;
00865             }
00866             if (tcp_info->srtt8 == INT16_MAX) {
00867                 tcp_info->srtt8 = R << 3; // srtt := R
00868                 tcp_info->srttvar4 = R << (2-1); // rttvar := R / 2
00869             } else {
00870                 /* 1/8 gain and scaling on smoothed RTT measurement */
00871                 int16_t R_diff = R - (tcp_info->srtt8 >> 3);
00872                 tcp_info->srtt8 += R_diff;
00873                 if (R_diff < 0) {
00874                     R_diff = -R_diff;
00875                 }
00876                 /* 1/4 gain and scaling on smoothed RTTVAR measurement */
00877                 int16_t V_diff = R_diff - (tcp_info->srttvar4 >> 2);
00878                 tcp_info->srttvar4 += V_diff;
00879             }
00880             /* RTO = RTT + 4 * RTTVAR - rounds nicely as described by Van Jacobsen */
00881             tcp_info->rto = (tcp_info->srtt8 >> 3) + tcp_info->srttvar4;
00882             if (tcp_info->rto < TCP_MINIMUM_RTO) {
00883                 tcp_info->rto = TCP_MINIMUM_RTO;
00884             }
00885             //tr_debug("R=%"PRId16" rto=%"PRIu16" srtt8=%"PRId16" rttvar4=%"PRId16, R, tcp_info->rto, tcp_info->srtt8, tcp_info->srttvar4);
00886             //tr_debug("R=%.2f rto=%.2f srtt=%.2f rttvar=%.2f", R * .150F, tcp_info->rto * .150F, tcp_info->srtt8 * (.15F/8), tcp_info->srttvar4 * (.15F/4));
00887         }
00888         tcp_info->retry = 0;
00889         tcp_info->timer = 0;
00890 
00891         if (remaining_bytes ||
00892             ((state_flag[tcp_info->state] & TCP_FLAG_FIN) && !tcp_info->sent_fin)) {
00893             tcp_segment_start(tcp_info, false);
00894         } else {
00895             tcp_info->busy = false;
00896         }
00897     }
00898 }
00899 
00900 
00901 /**
00902  * \brief Function called every time timer ticks.
00903  */
00904 
00905 static void tcp_timer_handle(uint16_t ticksUpdate)
00906 {
00907     arm_event_s event = {
00908         .receiver = socket_event_handler_id_get(),
00909         .sender = 0,
00910         .event_type = ARM_SOCKET_TCP_TIMER_CB,
00911         .event_data = ticksUpdate,
00912         .data_ptr = NULL,
00913         .priority = ARM_LIB_LOW_PRIORITY_EVENT,
00914     };
00915     if (eventOS_event_send(&event) != 0) {
00916         tr_error("tcp_timer_handle(): event send failed");
00917     }
00918 }
00919 
00920 /**
00921  * \brief Function used for handling time events.
00922  */
00923 
00924 void tcp_handle_time_event(uint16_t tickUpdate)
00925 {
00926     if (tcp_session_count == 0) {
00927         return;
00928     }
00929 
00930     ns_list_foreach_safe(socket_t, socket, &socket_list) {
00931         if (!socket_is_ipv6(socket) || socket->type != SOCKET_TYPE_STREAM) {
00932             continue;
00933         }
00934         inet_pcb_t *inet_pcb = socket->inet_pcb ;
00935         tcp_session_t *cur = inet_pcb->session ;
00936         if (cur && cur->timer) {
00937             if (cur->timer > tickUpdate) {
00938                 cur->timer -= tickUpdate;
00939             } else {
00940                 cur->timer = 0;
00941                 if (inet_pcb->socket->flags  & SOCKET_LISTEN_STATE) {
00942                     //shouldn't happen
00943                 } else if (cur->state == TCP_STATE_CLOSED) {
00944                     //tcp_timers_active &= ~the_bit;
00945                 } else if (cur->state == TCP_STATE_TIME_WAIT) {
00946                     //tr_debug("Timewait --> Close");
00947                     tcp_session_delete(cur);
00948                 } else {
00949                     if (cur->busy) {
00950                         cur->rto *= 2;
00951                         if (cur->rto > TCP_MAXIMUM_RTO) {
00952                             cur->rto = TCP_MAXIMUM_RTO;
00953                         }
00954                         cur = tcp_resend_segment(cur);
00955                     } else if (cur->state == TCP_STATE_FIN_WAIT_2) {
00956                         if (inet_pcb->socket->flags  & SOCKET_FLAG_CLOSED) {
00957                             tr_debug("sTW No Fin from host yet"); // Timeout shouldn't happen if socket is still open, so logically no event needed
00958                             cur->state = TCP_STATE_TIME_WAIT;
00959                             cur->timer = TCP_TIME_WAIT_TO_CLOSE;
00960                         } else {
00961                             tr_err("FW2 timeout with socket open");
00962                         }
00963                     }
00964                 }
00965             }
00966         }
00967     }
00968 
00969     // XXX is this right? Surely should check current session list.
00970     // Guess we just get one more tick though, as we won't re-set next time.
00971     protocol_timer_start(PROTOCOL_TIMER_TCP_TIM, tcp_timer_handle, TCP_TIMER_PERIOD);
00972 }
00973 
00974 /* find listen socket from socket instances */
00975 static socket_t *tcp_find_listen_socket(const uint8_t addr[static 16], uint16_t port)
00976 {
00977     FUNC_ENTRY_TRACE("tcp_find_listen_socket() %d", port);
00978     ns_list_foreach(socket_t, so, &socket_list) {
00979         if ((so->flags  & SOCKET_LISTEN_STATE) &&
00980             socket_is_ipv6(so) &&
00981             so->inet_pcb ->local_port  == port &&
00982             (addr_ipv6_equal(so->inet_pcb ->local_address , ns_in6addr_any) ||
00983              addr_ipv6_equal(so->inet_pcb ->local_address , addr))
00984             ) {
00985             return so;
00986         }
00987     }
00988 
00989     return NULL;
00990 }
00991 
00992 /**
00993  * \brief Function used for sending data through TCP.
00994  *
00995  * \param buf buffer to be sent
00996  * \param tcp_info points to TCP session
00997  *
00998  * Input: data = TCP payload
00999  *        options.code = TCP flags (or 0 meaning "normal data from socket" or 0xFF meaning "ACK-only segment")
01000  *        src_sa and dst_sa need not be set
01001  * Output to IP down:
01002  *         data = IP payload
01003  *         src_sa and dst_sa addresses and ports filled in from session
01004  *         options.type = IPV6_NH_TCP
01005  *
01006  */
01007 
01008 static void tcp_build(buffer_t *buf, tcp_session_t *tcp_info)
01009 {
01010     uint16_t header_length = 20;
01011     uint8_t *ptr;
01012 
01013     if (!buf) {
01014         return;
01015     }
01016 
01017     if (!tcp_info) {
01018         buffer_free(buf);
01019         return;
01020     }
01021 
01022     FUNC_ENTRY_TRACE("tcp_build() s=%d", tcp_info->inet_pcb->socket->id);
01023 
01024     if (!tcp_info) {
01025         tr_error("DW No Session: dst: %s, src port: %d, dst port: %d", tr_ipv6(buf->dst_sa .address ), buf->src_sa .port ,
01026                 buf->dst_sa .port );
01027         buffer_free(buf);
01028         return;
01029     }
01030 
01031     if (buffer_data_length(buf) != 0 && tcp_info->sent_fin) {
01032         tr_error("TCP:DW send fail by state %02x", tcp_info->state);
01033         buffer_free(buf);
01034         return;
01035     }
01036 
01037     //Set Flags
01038     if (buf->options .code ) {
01039         /* options.code contains TCP flags when used with TCP */
01040         if (buf->options .code  == 0xff) {
01041             /* code == 0xff if ACK only */
01042             buf->options .code  = TCP_FLAG_ACK;
01043         }
01044         //tr_debug("options from icmp");
01045     } else {
01046         /* data send request from socket */
01047         buf->options .code  = state_flag[tcp_info->state];
01048         uint16_t buf_len = buffer_data_length(buf);
01049         if (tcp_info->inet_pcb->socket->sndq.data_bytes <= buf_len) {
01050             /* push data if we have no more (RFC 1122 4.2.2.2) */
01051             if (buffer_data_length(buf) != 0) {
01052                 buf->options .code  |= TCP_FLAG_PSH;
01053             }
01054         } else {
01055             /* Close advances state even while outstanding data (more like BSD
01056              * than RFC 793), so make sure FIN flag only actually sent when no
01057              * more data */
01058             buf->options .code  &= ~TCP_FLAG_FIN;
01059         }
01060     }
01061 
01062     if (buf->options .code  != 0xff) {
01063         if (buf->options .code  & TCP_FLAG_SYN) {
01064             header_length += 4;
01065         }
01066     }
01067 
01068     buf = buffer_headroom(buf, header_length);
01069 
01070     if (!buf) {
01071         tr_error("TCP_DW:HeadROOM Fail");
01072         return;
01073     }
01074 
01075     ptr = buffer_data_reserve_header(buf, header_length);
01076 
01077     ptr = common_write_16_bit(tcp_info->inet_pcb->local_port, ptr);
01078     ptr = common_write_16_bit(tcp_info->inet_pcb->remote_port, ptr);
01079 
01080     ptr = common_write_32_bit(tcp_info->send_next, ptr);
01081     ptr = common_write_32_bit(tcp_info->receive_next, ptr);
01082 
01083     *ptr++ = header_length << 2; /* data offset */
01084 
01085     *ptr++ = buf->options .code ;
01086 
01087     tcp_compute_window_incr(tcp_info);
01088 
01089     ptr = common_write_16_bit(tcp_info->receive_adv - tcp_info->receive_next, ptr);
01090 
01091     ptr = common_write_32_bit(0, ptr); /* checksum and URG pointer */
01092 
01093     /* Advertise a minimal MSS based on minimum IPv6 MTU; keeping it simple for
01094      * now, rather than actually looking at the real link MTUs. See RFC 6991,
01095      * RFC 1191, etc.
01096      */
01097     if (buf->options .code  & TCP_FLAG_SYN) {
01098         *ptr++ = TCP_OPTION_MSS;
01099         *ptr++ = 4; // option length
01100         ptr = common_write_16_bit(tcp_info->receive_mss, ptr);
01101     }
01102 
01103     memcpy(buf->dst_sa .address , tcp_info->inet_pcb->remote_address, 16);
01104     buf->dst_sa .port  = tcp_info->inet_pcb->remote_port;
01105     buf->dst_sa .addr_type  = ADDR_IPV6 ;
01106     memcpy(buf->src_sa .address , tcp_info->inet_pcb->local_address, 16);
01107     buf->src_sa .port  = tcp_info->inet_pcb->local_port;
01108     buf->src_sa .addr_type  = ADDR_IPV6 ;
01109 
01110     /* calculate checksum */
01111     common_write_16_bit(buffer_ipv6_fcf(buf, IPV6_NH_TCP), buffer_data_pointer(buf) + 16);
01112 
01113     tcp_uack_segment(buf, tcp_info, header_length);
01114 
01115     buf->info  = (buffer_info_t)(B_FROM_TCP | B_TO_IPV6 | B_DIR_DOWN);
01116     buf->options .type  = IPV6_NH_TCP;
01117     buf->options .code  = 0;
01118 
01119     tcp_set_metadata(tcp_info->inet_pcb, buf);
01120 
01121 #ifdef TCP_TEST
01122     if (tx_drops[tcp_info->state]) {
01123         tx_drops[tcp_info->state]--;
01124         tr_info("TX drop %s", tcp_state_name(tcp_info));
01125         socket_tx_buffer_event_and_free(buf, SOCKET_TX_FAIL);
01126         return;
01127     }
01128 #endif
01129 
01130     //tr_debug("DW buf_len=%d", buffer_data_length(buf));
01131     protocol_push(buf);
01132 }
01133 
01134 static void tcp_session_established(protocol_interface_info_entry_t *cur, tcp_session_t *tcp_info)
01135 {
01136     tr_debug("UP:sES");
01137     socket_t *so = tcp_info->inet_pcb ->socket;
01138     socket_connection_complete(so, cur->id );
01139     tcp_info->state = TCP_STATE_ESTABLISHED;
01140     /* RFC 6298 - if timed out during connection, revert to conservative initial RTO for data */
01141     /* (What's the point - Karn's algorithm would cover this?) */
01142     if (tcp_info->retry > 0 && tcp_info->rto < TCP_INITIAL_CONSERVATIVE_RTO) {
01143         tcp_info->rto = TCP_INITIAL_CONSERVATIVE_RTO;
01144     }
01145 }
01146 /**
01147  * \brief Function that handles data coming from lower level to TCP.
01148  *
01149  * \param buf buffer received
01150  *
01151  * \return allocated pointer if acknowledgment needs to be sent
01152  * \return zero pointer, no further action required
01153  */
01154 
01155 buffer_t *tcp_up(buffer_t *buf)
01156 {
01157     uint8_t *ptr;
01158     protocol_interface_info_entry_t *cur;
01159     uint16_t data_offset;
01160     uint16_t mss_option = 536;
01161     uint16_t window_size;
01162     inet_pcb_t *inet_pcb;
01163     tcp_session_t *tcp_info;
01164     buffer_t *segment_ack = NULL;
01165     uint32_t ack_no;
01166     uint32_t seq_no;
01167     uint16_t seg_len;
01168     uint8_t flags;
01169 
01170     cur = buf->interface ;
01171 
01172     /* Multicast source or link-layer destination already handled by IP */
01173     if (!cur || addr_is_ipv6_multicast(buf->dst_sa .address ) || buf->options .ll_security_bypass_rx ) {
01174         tr_error("TCP UP:Invalid");
01175         return buffer_free(buf);
01176     }
01177 
01178     if (buffer_data_length(buf) < 20) {
01179         tr_error("TCP UP:Too short");
01180         return buffer_free(buf);
01181     }
01182 
01183     if (buffer_ipv6_fcf(buf, IPV6_NH_TCP)) {
01184         tr_warn("TCP CKSUM ERROR!!!: src: %s, dst: %s", tr_ipv6(buf->src_sa .address ), tr_ipv6(buf->dst_sa .address ));
01185         protocol_stats_update(STATS_IP_CKSUM_ERROR, 1);
01186         return buffer_free(buf);
01187     }
01188 
01189     // save received port(s), seq_no and ack_no, data_offset, flags, window_size,
01190     ptr = buffer_data_pointer(buf);
01191     buf->src_sa .port  = common_read_16_bit(ptr);
01192     ptr += 2;
01193     buf->dst_sa .port  = common_read_16_bit(ptr);
01194     ptr += 2;
01195     seq_no = common_read_32_bit(ptr);
01196     ptr += 4;
01197     ack_no = common_read_32_bit(ptr);
01198     ptr += 4;
01199 
01200     data_offset = (*ptr++ >> 4) << 2;
01201     if (data_offset > buffer_data_length(buf)) {
01202         tr_error("TCP UP:Offset length fail");
01203         return buffer_free(buf);
01204     }
01205 
01206     buffer_data_strip_header(buf, data_offset);
01207 
01208     flags = *ptr++;
01209     window_size = common_read_16_bit(ptr);
01210     ptr += 2;
01211 
01212     // Skip over Checksum (already checked) and Urgent Pointer (ignored)
01213     ptr += 4;
01214 
01215     seg_len = buffer_data_length(buf);
01216     if (flags & TCP_FLAG_SYN) {
01217         seg_len++;
01218     }
01219     if (flags & TCP_FLAG_FIN) {
01220         seg_len++;
01221     }
01222 
01223     tr_debug("TCP_UP: dst_p=%d, src_p=%d, flags=%s", buf->dst_sa .port , buf->src_sa .port , trace_tcp_flags(flags));
01224     /* clear flags that will be ignored */
01225     flags &= ~(TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG);
01226 
01227     // Parse options
01228     bool malformed_options = false;
01229     if (data_offset > 20) {
01230         uint16_t options_len = data_offset - 20;
01231         while (options_len > 0) {
01232             uint8_t type = ptr[0];
01233             uint8_t len;
01234             if (type == TCP_OPTION_END) {
01235                 break;
01236             } else if (type == TCP_OPTION_NOP) {
01237                 len = 1;
01238             } else {
01239                 if (options_len < 2) {
01240                     goto bad_opts;
01241                 }
01242                 len = ptr[1];
01243                 if (len < 2) {
01244                     goto bad_opts;
01245                 }
01246             }
01247 
01248             if (len > options_len) {
01249             bad_opts:
01250                 malformed_options = true;
01251                 tr_err("Malformed options");
01252                 break;
01253             }
01254 
01255             if (type == TCP_OPTION_MSS && len == 4) {
01256                 mss_option = common_read_16_bit(ptr + 2);
01257                 tr_debug("MSS %"PRIu16, mss_option);
01258             } else if (type != TCP_OPTION_NOP){
01259                 tr_info("Unsupported option %d", type);
01260             }
01261             ptr += len;
01262             options_len -= len;
01263         }
01264     }
01265 
01266     // find socket from existing connections based on local and remote addresses
01267     socket_t *so = socket_lookup_ipv6(IPV6_NH_TCP, &buf->dst_sa , &buf->src_sa , false);
01268     inet_pcb = so ? so->inet_pcb  : NULL;
01269     tcp_info = inet_pcb ? inet_pcb->session  : NULL;
01270     // if not found, and it's a SYN, look for a listening socket
01271     if (tcp_info == NULL && !malformed_options) find_listen: { // Can jump here from TIME-WAIT, with tcp_info set
01272         socket_t *listen_socket = tcp_find_listen_socket(buf->dst_sa .address , buf->dst_sa .port );
01273         if (listen_socket) {
01274             tr_debug("UP: Packet for LISTEN socket %d", listen_socket->id );
01275 #ifdef TCP_TEST
01276             if (rx_drops[TCP_STATE_LISTEN]) {
01277                 tr_info("RX drop LISTEN");
01278                 rx_drops[TCP_STATE_LISTEN]--;
01279                 return buffer_free(buf);
01280             }
01281 #endif
01282             if (flags & TCP_FLAG_RST) {
01283                 tr_warn("UP, RST to LISTEN");
01284                 return buffer_free(buf);
01285             }
01286             if (flags & TCP_FLAG_ACK) {
01287                 tr_warn("UP, ACK to LISTEN");
01288                 return tcp_reset_response(NULL, 0, buf, ack_no, 0, TCP_FLAG_RST);
01289             }
01290             if (flags & TCP_FLAG_SYN) {
01291                 socket_t *new_socket = socket_new_incoming_connection(listen_socket);
01292                 if (!new_socket) {
01293                     tr_error("Couldn't allocate socket");
01294                     return buffer_free(buf);
01295                 }
01296                 inet_pcb = new_socket->inet_pcb ;
01297                 /* new socket has an inet PCB cloned from the listening one - lock down addresses+ports */
01298                 memcpy(inet_pcb->remote_address , buf->src_sa .address , 16);
01299                 memcpy(inet_pcb->local_address , buf->dst_sa .address , 16);
01300                 inet_pcb->local_port  = buf->dst_sa .port ;
01301                 inet_pcb->remote_port  = buf->src_sa .port ;
01302                 tr_debug("remote=[%s]:%u", trace_ipv6(inet_pcb->remote_address ), inet_pcb->remote_port );
01303                 tr_debug("local=[%s]:%u", trace_ipv6(inet_pcb->local_address ), inet_pcb->local_port );
01304                 /* If someone sets a fixed (non-0) flow label on a listening socket, all incoming
01305                  * connections will end up using the same flow label, which is dumb, but user's fault. */
01306                 /* Same logic as connect(). */
01307                 if (inet_pcb->flow_label == IPV6_FLOW_AUTOGENERATE ||
01308                         (inet_pcb->flow_label == IPV6_FLOW_UNSPECIFIED && ipv6_flow_auto_label)) {
01309                     inet_pcb->flow_label = ipv6_flow_random();
01310                 }
01311                 tcp_info = tcp_session_ptr_allocate(inet_pcb, tcp_info);
01312                 if (!tcp_info) {
01313                     tr_error("Couldn't allocate TCP session");
01314                     socket_release(new_socket);
01315                     return buffer_free(buf);
01316                 }
01317                 // save source port and address to tcp session data
01318                 tcp_info->interface = cur;
01319 
01320                 if (tcp_info->interface->nwk_id == IF_6LoWPAN) {
01321                     if (tcp_info->receive_mss > TCP_LOWPAN_MSS_LIMIT) {
01322                         tcp_info->receive_mss = TCP_LOWPAN_MSS_LIMIT;
01323                     }
01324                 }
01325 
01326                 tcp_info->receive_next = seq_no;
01327                 tcp_info->receive_adv = seq_no;
01328                 tcp_info->send_window = window_size;
01329                 tcp_info->send_mss_peer = mss_option;
01330                 tcp_rethink_mss(tcp_info);
01331                 buffer_free(buf);
01332                 // Acknowledge 1 byte (the SYN) - ignore anything further
01333                 buf = tcp_ack_buffer(tcp_info, 1);
01334                 if (!buf) {
01335                     tr_error("Couldn't create SYN-ACK");
01336                     tcp_session_delete(tcp_info);
01337                     socket_release(new_socket);
01338                     return NULL;
01339                 }
01340                 buf->options .code  = TCP_FLAG_SYN | TCP_FLAG_ACK;
01341 
01342                 tr_debug("UP:sSR");
01343                 tcp_info->state = TCP_STATE_SYN_RECEIVED;
01344                 tcp_info->passive_open = true;
01345                 tcp_build(buf, tcp_info);
01346                 return NULL;
01347             } // SYN
01348             // Not RST, ACK or SYN
01349             tr_warn("UP, no flags to LISTEN");
01350             return buffer_free(buf);
01351         } // Listening socket found
01352 
01353         // Wipe out tcp_info, for the case where we jumped into this block from TIME-WAIT, so we send
01354         // a reset (for this new connection attempt, with a higher sequence number, for which
01355         // we have no listening socket).
01356         tcp_info = NULL;
01357     } // No existing session
01358 
01359     if (tcp_info == NULL || tcp_info->state == TCP_STATE_CLOSED || malformed_options) {
01360         tr_info("No tcp_info for port=%d from %s", buf->dst_sa .port , trace_ipv6(buf->src_sa .address ));
01361         if (flags & TCP_FLAG_RST) {
01362             tr_debug("RST to CLOSED");
01363             return buffer_free(buf);
01364         }
01365         if (!(flags & TCP_FLAG_ACK)) {
01366             return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, 0, seq_no + seg_len, TCP_FLAG_RST|TCP_FLAG_ACK);
01367         }
01368         return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, ack_no, 0, TCP_FLAG_RST);
01369     }
01370 
01371 #ifdef TCP_TEST
01372     if (rx_drops[tcp_info->state]) {
01373         tr_info("RX drop %s", tcp_state_name(tcp_info));
01374         rx_drops[tcp_info->state]--;
01375         return buffer_free(buf);
01376     }
01377 #endif
01378 
01379     buffer_socket_set(buf, so);
01380 
01381     tr_debug("UP: sock=%d: state=%s", so->id , tcp_state_name(tcp_info));
01382 
01383     if (tcp_info->state == TCP_STATE_SYN_SENT) {
01384         if (flags & TCP_FLAG_ACK) {
01385             if (ack_no != tcp_info->send_next) {
01386                 if (flags & TCP_FLAG_RST) {
01387                     return buffer_free(buf);
01388                 }
01389                 return tcp_reset_response(NULL, 0, buf, ack_no, 0, TCP_FLAG_RST);
01390             }
01391         }
01392         if (flags & TCP_FLAG_RST) {
01393             if (flags & TCP_FLAG_ACK) {
01394                 tcp_session_delete_with_error(tcp_info, SOCKET_CONNECT_FAIL);
01395             }
01396             return buffer_free(buf);
01397         }
01398         if (flags & TCP_FLAG_SYN) {
01399             tcp_info->receive_next = seq_no;
01400             tcp_info->receive_adv = seq_no;
01401             tcp_info->send_mss_peer = mss_option;
01402             tcp_rethink_mss(tcp_info);
01403             if (flags & TCP_FLAG_ACK) {
01404                 tcp_ack_segment(ack_no, tcp_info);
01405                 tcp_info->send_wl1 = seq_no; // RFC 1122 4.2.2.20(c)
01406                 tcp_info->send_wl2 = ack_no;
01407                 tcp_info->send_window = window_size;
01408                 tcp_session_established(cur, tcp_info);
01409                 goto syn_sent_to_established;
01410             } else {
01411                 tr_debug("UP:sSR");
01412                 tcp_info->state = TCP_STATE_SYN_RECEIVED;
01413                 segment_ack = tcp_ack_buffer(tcp_info, 1);
01414                 if (segment_ack) {
01415                     buffer_socket_set(segment_ack, buf->socket );
01416                     segment_ack->options .code  = TCP_FLAG_SYN | TCP_FLAG_ACK;
01417                     tcp_build(segment_ack, tcp_info);
01418                 }
01419                 buffer_free(buf);
01420                 return NULL;
01421             }
01422         }
01423     } // state == TCP_STATE_SYN_SENT
01424 
01425     // Early escape from TIME-WAIT: processing of SYN segments as per RFC 6191
01426     // (simple non-timestamp case)
01427     if ((flags & (TCP_FLAG_SYN|TCP_FLAG_FIN|TCP_FLAG_ACK|TCP_FLAG_RST)) == TCP_FLAG_SYN && tcp_info->state == TCP_STATE_TIME_WAIT) {
01428         if (tcp_seq_ge(seq_no, tcp_info->receive_next)) {
01429             goto find_listen;
01430         } else {
01431             return buffer_free(buf);
01432         }
01433     }
01434 
01435     // Window checks
01436     int32_t receive_window = sockbuf_space(&so->rcvq);
01437     if (receive_window < 0) {
01438         receive_window = 0;
01439     }
01440     if (receive_window < (int32_t) (tcp_info->receive_adv - tcp_info->receive_next)) {
01441         receive_window = tcp_info->receive_adv - tcp_info->receive_next;
01442     }
01443 
01444     bool seq_ok = false;
01445     if (receive_window == 0) {
01446         if (seg_len == 0 && seq_no == tcp_info->receive_next) {
01447             seq_ok = true;
01448         }
01449     } else {
01450         if (tcp_seq_in_range(tcp_info->receive_next, seq_no, tcp_info->receive_next + receive_window - 1)) {
01451             seq_ok = true;
01452         } else if (seg_len > 0 && tcp_seq_in_range(tcp_info->receive_next, seq_no + seg_len - 1, tcp_info->receive_next + receive_window - 1)) {
01453             seq_ok = true;
01454         }
01455     }
01456 
01457     if (!seq_ok) {
01458         tr_debug("Out-of-window seq_no=%"PRIu32", seg_len=%"PRIu16", window [%"PRIu32" - %"PRIu32")", seq_no, seg_len, tcp_info->receive_next, tcp_info->receive_next + receive_window);
01459         buffer_free(buf);
01460         buf = tcp_ack_buffer(tcp_info, 0);
01461         tcp_build(buf, tcp_info);
01462         return NULL;
01463     }
01464 
01465     /* Strip data preceding the window */
01466     if (tcp_seq_lt(seq_no, tcp_info->receive_next)) {
01467         uint16_t excess = tcp_info->receive_next - seq_no;
01468         tr_debug("Strip preceding excess %d", excess);
01469         /* Strip SYN "byte" */
01470         if (flags & TCP_FLAG_SYN) {
01471             flags &= ~TCP_FLAG_SYN;
01472             seg_len--;
01473             excess--;
01474             seq_no++;
01475         }
01476         if (excess) {
01477             buffer_data_strip_header(buf, excess);
01478             seg_len -= excess;
01479             seq_no += excess;
01480         }
01481     }
01482 
01483     /* Strip data following the window */
01484     if (tcp_seq_gt(seq_no + buffer_data_length(buf), tcp_info->receive_next + receive_window)) {
01485         uint16_t excess = (seq_no + buffer_data_length(buf)) - (tcp_info->receive_next + receive_window);
01486         tr_debug("Strip trailing excess %d", excess);
01487         /* Strip FIN "byte" */
01488         if (flags & TCP_FLAG_FIN) {
01489             flags &= ~TCP_FLAG_FIN;
01490             seg_len--;
01491         }
01492         buf->buf_end  -= excess;
01493         seg_len -= excess;
01494     }
01495 
01496     if (flags & TCP_FLAG_RST) {
01497         switch (tcp_info->state) {
01498             case TCP_STATE_SYN_RECEIVED:
01499                 if (tcp_info->passive_open) {
01500                     tcp_session_delete_with_error(tcp_info, 0);
01501                 } else {
01502                     tcp_session_delete_with_error(tcp_info, SOCKET_CONNECT_FAIL);
01503                 }
01504                 break;
01505             case TCP_STATE_ESTABLISHED:
01506             case TCP_STATE_FIN_WAIT_1:
01507             case TCP_STATE_FIN_WAIT_2:
01508             case TCP_STATE_CLOSE_WAIT:
01509                 tcp_session_delete_with_error(tcp_info, SOCKET_CONNECTION_RESET);
01510                 break;
01511             case TCP_STATE_CLOSING:
01512             case TCP_STATE_LAST_ACK:
01513                 tcp_session_delete(tcp_info);
01514                 break;
01515             case TCP_STATE_TIME_WAIT: // RFC 1337
01516             default:
01517                 break;
01518         }
01519         return buffer_free(buf);
01520     }
01521 
01522     if (flags & TCP_FLAG_SYN) {
01523         tr_debug("unexpected SYN");
01524         if (tcp_info->state == TCP_STATE_SYN_RECEIVED && tcp_info->passive_open) {
01525             // RFC 1122 4.2.2.20(e)
01526             tcp_session_delete_with_error(tcp_info, 0); // really no reset sent?
01527             return buffer_free(buf);
01528         }
01529         if (!(flags & TCP_FLAG_ACK)) {
01530             return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, 0, seq_no + seg_len, TCP_FLAG_RST|TCP_FLAG_ACK);
01531         }
01532         return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, ack_no, 0, TCP_FLAG_RST);
01533     }
01534 
01535     if (!(flags & TCP_FLAG_ACK)) {
01536         tr_debug("ACK not set");
01537         return buffer_free(buf);
01538     }
01539 
01540     if (tcp_info->state == TCP_STATE_SYN_RECEIVED) {
01541         if (ack_no == tcp_info->send_next) {
01542             tcp_info->send_wl1 = seq_no;  // RFC 1122 4.2.2.20(f)
01543             tcp_info->send_wl2 = ack_no;
01544             tcp_info->send_window = window_size;
01545             tcp_session_established(cur, tcp_info);
01546         } else {
01547             return tcp_reset_response(NULL, 0, buf, ack_no, 0, TCP_FLAG_RST);
01548         }
01549     }
01550 
01551     if (tcp_seq_lt(ack_no, tcp_info->send_unacknowledged)) {
01552         tr_debug("Already acked ack_no=%"PRIu32", in-flight [%"PRIu32" - %"PRIu32")", ack_no, tcp_info->send_unacknowledged, tcp_info->send_next);
01553     } else if (tcp_seq_gt(ack_no, tcp_info->send_next)) {
01554         tr_debug("Future ack ack_no=%"PRIu32", in-flight [%"PRIu32" - %"PRIu32")", ack_no, tcp_info->send_unacknowledged, tcp_info->send_next);
01555         buffer_free(buf);
01556         // Generating this ack can lead to an ack storm if we're somehow out of sync...
01557         // Seems to be a TCP flaw...
01558         buf = tcp_ack_buffer(tcp_info, 0);
01559         tcp_build(buf, tcp_info);
01560         return NULL;
01561     } else /* SND.UNA <= SEG.ACK <= SND.NXT */ {
01562         /* Update window, if packet not older than last window information */
01563         if (tcp_seq_gt(seq_no, tcp_info->send_wl1) ||
01564                 (seq_no == tcp_info->send_wl1 && tcp_seq_ge(ack_no, tcp_info->send_wl2))) {
01565             if (tcp_info->send_window != window_size) {
01566                 tr_debug("Send window update %"PRIu16"->%"PRIu16, tcp_info->send_window, window_size);
01567             }
01568             tcp_info->send_wl1 = seq_no;
01569             tcp_info->send_wl2 = ack_no;
01570             tcp_info->send_window = window_size;
01571             // Watch out for shrinking right edge
01572             if (window_size == 0 && ack_no != tcp_info->send_next) {
01573                 tcp_info->persist = true;
01574             }
01575         }
01576         if (ack_no != tcp_info->send_unacknowledged) {
01577             tr_debug("New ack_no=%"PRIu32", in-flight [%"PRIu32" - %"PRIu32")", ack_no, tcp_info->send_unacknowledged, tcp_info->send_next);
01578             tcp_ack_segment(ack_no, tcp_info);
01579         } else if (tcp_info->persist) {
01580             tcp_info->retry = 0;
01581             if (window_size != 0) {
01582                 tcp_info->persist = false;
01583                 // Got a pure window update. (Re)transmit now
01584                 tcp_resend_segment(tcp_info);
01585             } else {
01586                 // Let the retransmit timer keep on running, which will trigger
01587                 // another persist probe at RTO after the last one (effectively
01588                 // ignoring this ack for timing purposes), but reset the retry
01589                 // count so we don't give up in resend_segment.
01590             }
01591         }
01592 
01593         bool fin_acknowledged = tcp_info->sent_fin && tcp_info->send_unacknowledged == tcp_info->send_next;
01594         switch (tcp_info->state) {
01595             case TCP_STATE_FIN_WAIT_1:
01596                 if (fin_acknowledged) {
01597                     tcp_info->state = TCP_STATE_FIN_WAIT_2;
01598                     // Only time out FIN_WAIT_2 if no longer have a socket
01599                     if (so->flags  & SOCKET_FLAG_CLOSED) {
01600                         tcp_info->timer = TCP_FIN_WAIT_2_TIMEOUT;
01601                     } else {
01602                         tcp_info->timer = 0;
01603                     }
01604                     tr_debug("UP:sF2");
01605                 }
01606                 break;
01607             case TCP_STATE_CLOSING:
01608                 if (fin_acknowledged) {
01609                     tcp_info->state = TCP_STATE_TIME_WAIT;
01610                     tr_debug("UP:sTW");
01611                     tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE;
01612                 }
01613                 break;
01614             case TCP_STATE_LAST_ACK:
01615                 if (fin_acknowledged) {
01616                     socket_event_push(SOCKET_CONNECT_CLOSED, so, cur->id , NULL, 0);
01617                     tr_debug("Last ACK remove Session");
01618                     tcp_session_delete(tcp_info);
01619                     return buffer_free(buf);
01620                 }
01621                 break;
01622             case TCP_STATE_TIME_WAIT:
01623                 tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE;
01624                 break;
01625         }
01626     }
01627 
01628 syn_sent_to_established:
01629     if (flags & TCP_FLAG_URG) {
01630         /* No handling of urgent */
01631     }
01632 
01633     /* This is the point we're actually processing incoming text or FINs. All of the
01634      * above is done as long as in-window, but from here on we need the correct sequence.
01635      * seg_len is length including FIN marker.
01636      */
01637     if (seg_len > 0 && seq_no != tcp_info->receive_next) {
01638         tr_debug("Out-of-order data");
01639         buffer_t *ack_buf = tcp_ack_buffer(tcp_info, 0);
01640         tcp_build(ack_buf, tcp_info);
01641         return buffer_free(buf);
01642     }
01643 
01644     /* Data only processed in some states - other states silently ignore */
01645     if (buffer_data_length(buf) &&
01646             (tcp_info->state == TCP_STATE_ESTABLISHED || tcp_info->state == TCP_STATE_FIN_WAIT_1 || tcp_info->state == TCP_STATE_FIN_WAIT_2)) {
01647         // This handles closed sockets (see RFC 1122 4.2.2.13 and RFC2525 2.16)
01648         // and also extends it to read shutdown (like Windows, apparently, but not Linux or BSD)
01649         if (so->flags  & SOCKET_FLAG_CANT_RECV_MORE) {
01650             tr_warn("Excess data we can't receive - resetting");
01651             return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, ack_no, 0, TCP_FLAG_RST);
01652         }
01653         buf->info  = (buffer_info_t)(B_FROM_TCP | B_TO_NONE | B_DIR_UP);
01654 
01655         //tr_debug("data up");
01656         sockbuf_append_and_compress(&so->rcvq, buf);
01657         buf = NULL;
01658         if ((flags & (TCP_FLAG_FIN|TCP_FLAG_PSH)) || sockbuf_space(&so->rcvq) <= (int32_t) (so->rcvq.data_byte_limit / 2)) {
01659             socket_data_queued_event_push(so);
01660         }
01661     }
01662 
01663     // Original buffer no longer required
01664     if (buf) {
01665         buf = buffer_free(buf);
01666     }
01667 
01668     if (flags & TCP_FLAG_FIN) {
01669         tr_debug("fin");
01670         switch (tcp_info->state) {
01671             case TCP_STATE_SYN_RECEIVED: // can't happen?
01672             case TCP_STATE_ESTABLISHED:
01673                 tcp_info->state = TCP_STATE_CLOSE_WAIT;
01674                 tcp_info->timer = 0;
01675                 tr_debug("UP:sCW");
01676                 socket_cant_recv_more(so, cur->id );
01677                 break;
01678             case TCP_STATE_FIN_WAIT_1:
01679                 if (tcp_info->send_unacknowledged == tcp_info->send_next) {
01680                     tcp_info->state = TCP_STATE_TIME_WAIT;
01681                     tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE;
01682                     tr_debug("UP:sTW");
01683                 } else {
01684                     tcp_info->state = TCP_STATE_CLOSING;
01685                     tr_debug("UP:sCl");
01686                 }
01687                 socket_cant_recv_more(so, cur->id );
01688                 break;
01689             case TCP_STATE_FIN_WAIT_2:
01690                 tcp_info->state = TCP_STATE_TIME_WAIT;
01691                 tr_debug("UP:sTW");
01692                 tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE;
01693                 socket_cant_recv_more(so, cur->id );
01694                 socket_event_push(SOCKET_CONNECT_CLOSED, so, cur->id , 0, 0);
01695                 break;
01696             case TCP_STATE_TIME_WAIT:
01697                 tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE;
01698                 break;
01699             default:
01700                 tr_debug("UP:fin, other state");
01701                 // No action
01702                 break;
01703         }
01704     }
01705 
01706     // if there is new data to be acknowledged then send ack
01707     if (seg_len > 0) {
01708         segment_ack = tcp_ack_buffer(tcp_info, seg_len);
01709         tcp_build(segment_ack, tcp_info);
01710     }
01711     return buf;
01712 }
01713 
01714 const char *tcp_state_name(const tcp_session_t *tcp_info)
01715 {
01716     switch (tcp_info->state) {
01717         case TCP_STATE_LISTEN:
01718              return "LISTEN";
01719         case TCP_STATE_SYN_SENT:
01720             return "SYN-SENT";
01721         case TCP_STATE_SYN_RECEIVED:
01722             return "SYN-RECEIVED";
01723         case TCP_STATE_ESTABLISHED:
01724             return "ESTABLISHED";
01725         case TCP_STATE_CLOSE_WAIT:
01726             return "CLOSE-WAIT";
01727         case TCP_STATE_LAST_ACK:
01728             return "LAST-ACK";
01729         case TCP_STATE_FIN_WAIT_1:
01730             return "FIN-WAIT-1";
01731         case TCP_STATE_FIN_WAIT_2:
01732             return "FIN-WAIT-2";
01733         case TCP_STATE_CLOSING:
01734             return "CLOSING";
01735         case TCP_STATE_TIME_WAIT:
01736             return "TIME-WAIT";
01737         default:
01738             return "?";
01739     }
01740 }
01741 #endif /*NO_TCP*/
01742 /* end of file tcp.c */