Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp.c Source File

tcp.c

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