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