Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 */
Generated on Tue Jul 12 2022 13:54:55 by
