void TCP_Process_effective_close ( TCB_STRUCT_PTR tcb, /* IN/OUT - TCP context */ TCP_CFG_STRUCT_PTR tcp_cfg /* IN - TCP layer data */ ) { /* Body */ RTCSLOG_FNE2(RTCSLOG_FN_TCP_Process_effective_close, tcb->state); switch ( tcb->state ) { case SYN_RECEIVED: /* no data has been sent */ case ESTABLISHED: tcb->state = FINWAIT_1; TCP_Must_send_ack(tcb, tcp_cfg); break; case CLOSE_WAIT: tcb->state = LAST_ACK; TCP_Must_send_ack(tcb, tcp_cfg); break; default: RTCS_log_error(ERROR_TCP, RTCSERR_TCP_BAD_STATE_FOR_CLOSE, (uint_32)tcb->state, (uint_32)tcb, 0); break; } /* End Switch */ SOCK_select_signal(tcb->SOCKET, tcb->state); RTCSLOG_FNX1(RTCSLOG_FN_TCP_Process_effective_close); } /* Endbody */
HOSTENT_STRUCT *DNS_query_resolver_task ( unsigned char *name, uint16_t query_type ) { /* Body */ DNS_MESSAGE_HEADER_STRUCT *message_head_ptr; DNS_MESSAGE_TAIL_STRUCT *message_tail_ptr; HOSTENT_STRUCT *host_ptr = NULL; sockaddr_in addr; uint32_t local_sock; uint32_t qname_size; uint32_t buffer_size; uint16_t rlen; int32_t temp_size; int32_t error; unsigned char *temp_ptr; unsigned char *qname_ptr; unsigned char *buffer_ptr; /* ** If the size of this buffer is changed, also change the buffer size ** in the recvfrom() call near the bottom of this function */ buffer_ptr = RTCS_mem_alloc_zero( DNS_MAX_UDP_MESSAGE_SIZE ); if ( buffer_ptr == NULL ) { RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_ALLOCATE_MEMORY, 0, 0, 0); return( NULL ); }/* Endif */ _mem_set_type(buffer_ptr, MEM_TYPE_DNS_UDP_MESSAGE); qname_ptr = buffer_ptr + sizeof( DNS_MESSAGE_HEADER_STRUCT ); if ( query_type == DNS_A ) { error = DNS_is_dotted_domain_name( name, qname_ptr ); if ( error == RTCSERR_DNS_INVALID_NAME || error == RTCSERR_DNS_INVALID_LOCAL_NAME ) { _mem_free(buffer_ptr); return( NULL ); }/* Endif */ } else { if ( query_type == DNS_PTR ) { error = DNS_insert_IP_query( name, qname_ptr ); if ( error == RTCSERR_DNS_INVALID_IP_ADDR ) { _mem_free(buffer_ptr); return( NULL ); }/* Endif */ } else { _mem_free(buffer_ptr); return( NULL ); } /* Endif */ } /* Endif */ local_sock = socket(AF_INET, SOCK_DGRAM, 0); if ( local_sock == RTCS_HANDLE_ERROR ) { RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_OPEN_SOCKET, 0, 0, 0); _mem_free(buffer_ptr); return( NULL ); }/* Endif */ /* Local address */ addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; error = bind(local_sock, &addr, sizeof(addr)); if (error != RTCS_OK) { RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_BIND_SOCKET, 0, 0, 0); _mem_free(buffer_ptr); return( NULL ); } /* Endif */ /* set up buffer for sending query. */ message_head_ptr = (DNS_MESSAGE_HEADER_STRUCT *)buffer_ptr; mqx_htons(message_head_ptr->ID, 0); mqx_htons(message_head_ptr->CONTROL, DNS_STANDARD_QUERY); mqx_htons(message_head_ptr->QDCOUNT, DNS_SINGLE_QUERY); mqx_htons(message_head_ptr->NSCOUNT, 0); mqx_htons(message_head_ptr->ARCOUNT, 0); mqx_htons(message_head_ptr->ANCOUNT, 0); qname_size = strlen((char *)qname_ptr ); /* Need to include the last '\0' character as well */ qname_size++; temp_ptr = buffer_ptr + sizeof( DNS_MESSAGE_HEADER_STRUCT ) + qname_size; message_tail_ptr = (DNS_MESSAGE_TAIL_STRUCT *)temp_ptr; mqx_htons(message_tail_ptr->QTYPE, query_type); mqx_htons(message_tail_ptr->QCLASS, DNS_IN); buffer_size = sizeof(DNS_MESSAGE_HEADER_STRUCT) + qname_size + sizeof(DNS_MESSAGE_TAIL_STRUCT); /* Remote address, DNS_Resolver currently uses port 1024 */ addr.sin_port = DNS_RESOLVER_PORT; addr.sin_addr.s_addr = DNS_RESOLVER_IP_ADDR; rlen = sizeof(addr); /* Send the buffer to the resolver for making a query */ error = sendto(local_sock, buffer_ptr, buffer_size, 0, &addr, rlen); if (error == RTCS_ERROR) { shutdown(local_sock, FLAG_ABORT_CONNECTION); RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_SEND_QUERY, 0, 0, 0); _mem_free(buffer_ptr); return( NULL ); }/* Endif */ /* Get the response from the resolver, if none received, return NULL */ error = (uint32_t)RTCS_selectset( &local_sock, 1, DNS_QUERY_TIMEOUT ); if ( !error || error == RTCS_ERROR ) { shutdown(local_sock, FLAG_ABORT_CONNECTION); RTCS_log_error(ERROR_DNS, RTCSERR_DNS_NO_RESPONSE_FROM_RESOLVER, 0, 0, 0); _mem_free(buffer_ptr); return( NULL ); } /* Endif */ temp_size = recvfrom(local_sock, buffer_ptr, DNS_MAX_UDP_MESSAGE_SIZE, 0, &addr, &rlen); if ( temp_size == RTCS_ERROR ) { shutdown(local_sock, FLAG_ABORT_CONNECTION); RTCS_log_error(ERROR_DNS, RTCSERR_DNS_PACKET_RECEPTION_ERROR, 0, 0, 0); _mem_free(buffer_ptr); return( NULL ); }/* Endif */ host_ptr = DNS_parse_UDP_response(buffer_ptr, name, query_type); shutdown(local_sock, FLAG_ABORT_CONNECTION); _mem_free(buffer_ptr); return( host_ptr ); } /* Endbody */
HOSTENT_STRUCT *DNS_parse_UDP_response ( unsigned char *buffer_ptr, unsigned char *name_ptr, uint16_t query_type ) { /* Body */ DNS_MESSAGE_HEADER_STRUCT *message_head_ptr = NULL; DNS_RESPONSE_RR_MIDDLE_STRUCT *answer_middle; INTERNAL_HOSTENT_STRUCT *host_ptr = &RTCS_HOST; unsigned char *answer_ptr; unsigned char *answer_tail; unsigned char *temp_ptr; uint16_t response_length, answer_type, name_size, number_of_answers, num_queries; uint32_t i, name_index = 0; uint32_t j = 0; uint32_t k = 0; uint32_t buffer_size; uint32_t *addr_ptr; bool unknown_answer_type = FALSE; message_head_ptr = (DNS_MESSAGE_HEADER_STRUCT *)buffer_ptr; buffer_size = sizeof(DNS_MESSAGE_HEADER_STRUCT); temp_ptr = buffer_ptr + sizeof( DNS_MESSAGE_HEADER_STRUCT ); /* Zero the global HOSTENT_STRUCT */ _mem_zero((char *)host_ptr, sizeof(INTERNAL_HOSTENT_STRUCT)); /* Get the number of queries. */ num_queries = mqx_ntohs(message_head_ptr->QDCOUNT); for (i = 0; i < num_queries; i++) { name_size = 0; while( (mqx_ntohc(temp_ptr) != '\0') && name_size < DNS_MAX_CHARS_IN_NAME ) { name_size = name_size + mqx_ntohc(temp_ptr) + 1; temp_ptr = temp_ptr + mqx_ntohc(temp_ptr) + 1; } /* Endwhile */ /* To include the terminating NULL char */ name_size++; buffer_size += (name_size + sizeof(DNS_MESSAGE_TAIL_STRUCT)); temp_ptr += (1 + sizeof(DNS_MESSAGE_TAIL_STRUCT)); } /* Endfor */ number_of_answers = mqx_ntohs(message_head_ptr->ANCOUNT); if (number_of_answers > DNS_MAX_NAMES ) { number_of_answers = DNS_MAX_NAMES; } /* Endif */ host_ptr->HOSTENT.h_aliases = &host_ptr->ALIASES[0]; host_ptr->HOSTENT.h_addr_list = (char **)&host_ptr->ADDRESSES[0]; host_ptr->ADDRESSES[0] = NULL; host_ptr->HOSTENT.h_name = NULL; host_ptr->HOSTENT.h_length = sizeof( _ip_address ); for (i = 0; (i < number_of_answers) && (j < DNS_MAX_ADDRS) && (k < DNS_MAX_NAMES); i++ ) { answer_ptr = temp_ptr; name_size = 0; while( (mqx_ntohc(temp_ptr) != '\0') && name_size < DNS_MAX_CHARS_IN_NAME && !(mqx_ntohc(temp_ptr) & DNS_COMPRESSED_NAME_MASK)) { name_size += mqx_ntohc(temp_ptr); temp_ptr += mqx_ntohc(temp_ptr) + 1; } /* Endwhile */ if ( mqx_ntohc(temp_ptr) & DNS_COMPRESSED_NAME_MASK ) { temp_ptr++; }/* Endif */ temp_ptr++; answer_middle = (DNS_RESPONSE_RR_MIDDLE_STRUCT *)temp_ptr; response_length = mqx_ntohs(answer_middle->RDLENGTH); answer_type = mqx_ntohs(answer_middle->TYPE); temp_ptr += sizeof(DNS_RESPONSE_RR_MIDDLE_STRUCT); answer_tail = temp_ptr; temp_ptr += response_length; switch ( answer_type ) { case DNS_A: if ( host_ptr->HOSTENT.h_name == NULL ) { host_ptr->HOSTENT.h_name = (char *)DNS_parse_answer_name_to_dotted_form( buffer_ptr, answer_ptr, name_index ); name_index++; } /* Endif */ RTCS_HOST_ADDRS[j] = mqx_ntohl((unsigned char *)answer_tail); /* ** j is used in case BOTH CNAME and A data is received. If CNAME ** answer is first, will write into wrong address space if using ** i. */ host_ptr->ADDRESSES[j] = &RTCS_HOST_ADDRS[j]; j++; /* ** This is to assure that the first IP address used is the first ** one that was given */ host_ptr->IP_address = *host_ptr->ADDRESSES[0]; break; case DNS_PTR: if (query_type == DNS_PTR) { if (host_ptr->HOSTENT.h_name != NULL) { host_ptr->ALIASES[k] = host_ptr->HOSTENT.h_name; k++; } /* Endif */ host_ptr->HOSTENT.h_name = (char *)DNS_parse_answer_name_to_dotted_form( buffer_ptr, answer_tail, name_index ); name_index++; addr_ptr = RTCS_mem_alloc_zero( sizeof( _ip_address )); if ( addr_ptr == NULL ) { RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_ALLOCATE_MEMORY, 0, 0, 0); return( NULL ); }/* Endif */ *addr_ptr = *((_ip_address *)name_ptr); host_ptr->ADDRESSES[j] = addr_ptr; j++; host_ptr->IP_address = *host_ptr->ADDRESSES[0]; } else { host_ptr->ALIASES[k] = (char *) DNS_parse_answer_name_to_dotted_form( buffer_ptr, answer_tail, name_index ); name_index++; k++; } /* Endif */ break; case DNS_CNAME: /* the k is used for ALIASES as the j is used for ADDRESSES */ host_ptr->ALIASES[k] = (char *) DNS_parse_answer_name_to_dotted_form( buffer_ptr, answer_tail, name_index ); name_index++; k++; break; default: unknown_answer_type = TRUE; } /* Endswitch */ if ( unknown_answer_type == TRUE ) { break; }/* Endif */ host_ptr->ADDRESSES[j] = NULL; host_ptr->ALIASES[k] = NULL; host_ptr->HOSTENT.h_addrtype = mqx_ntohs(answer_middle->CLASS); } /* Endfor */ if ( number_of_answers == 0 ) { return( NULL ); } /* Endif */ return( &RTCS_HOST.HOSTENT ); } /* Endbody */
void TCP_Process_close ( TCP_PARM_PTR req_ptr /* IN/OUT - the open request */ ) { /* Body */ TCP_CFG_STRUCT_PTR tcp_cfg; TCB_STRUCT_PTR tcb; int_32 reply = RTCS_OK; tcp_cfg = RTCS_getcfg(TCP); tcb = req_ptr->TCB_PTR; if ( tcb == NULL ) { RTCSCMD_complete(req_ptr, RTCSERR_TCP_CONN_RLSD); return; } IF_TCP_STATS_ENABLED(tcp_cfg->STATS.ST_CONN_CLOSED++); if ( tcb->VALID != TCB_VALID_ID ) { reply = RTCSERR_TCP_CONN_RLSD; RTCS_log_error( ERROR_TCP, RTCSERR_TCP_BAD_STATE_FOR_CLOSE, (uint_32)tcb, (uint_32)tcb->state, 1 ); } else if ( tcb->state == CLOSED ) { /* This should be the standard case if the other side aborted. */ TCP_Process_release(tcb, tcp_cfg); } else if ( (tcb->status & TCPS_FINTOSEND) != 0 ) { /* Upper layer must have already given us a tcpCLOSE, so we * can generate an error here. */ reply = RTCSERR_TCP_CONN_CLOSING; } else { switch ( tcb->state ) { case LISTEN: case SYN_SENT: TCP_Close_TCB(tcb, RTCS_OK, tcp_cfg); case BOUND: TCP_Process_release(tcb, tcp_cfg); break; case SYN_RECEIVED: /* no data has been sent */ case ESTABLISHED: case CLOSE_WAIT: TCP_Event(tcb,TCPS_FINTOSEND); /* We can only effectively close if all data has been sent, * allowing us to send a FIN immediately; otherwise closing * is delayed (TCPS_FINTOSEND indicates that connection should * be closed as soon as all data is sent) */ if ( tcb->sndnxt == (tcb->sndbufseq + tcb->sndlen) ) { TCP_Process_effective_close(tcb, tcp_cfg); } else { /* ** Have to kick ourselves into sending the outstanding ** data or we'll sit here forever if the other side is ** just waiting. This would happen if we send w/o PUSH ** just before closing. */ TCP_Must_send_ack(tcb, tcp_cfg); } /* Endif */ break; default: /* we shouldn't reach here, but jic... */ RTCS_log_error( ERROR_TCP, RTCSERR_TCP_BAD_STATE_FOR_CLOSE, (uint_32)tcb, (uint_32)tcb->state, 2); reply = RTCSERR_TCP_NOT_CONN; break; } /* End Switch */ } /* Endif */ /* The socket will be freed as soon as we return to shutdown() */ if (tcb->VALID == TCB_VALID_ID) { tcb->SOCKET = 0; } /* Endif */ RTCSCMD_complete(req_ptr, reply); } /* Endbody */
uint_32 RTCS_create ( void ) { /* Body */ RTCS_DATA_PTR RTCS_data_ptr; SOCKET_CONFIG_STRUCT_PTR socket_cfg_ptr; uint_32 error; /* ** Check and see if this is the first time we have initialized, */ if (RTCS_get_data() != NULL) { return RTCSERR_INITIALIZED; } // RTCS_data_ptr = RTCS_mem_alloc_system_zero(sizeof(RTCS_DATA)); if (RTCS_data_ptr == NULL) { error = RTCSERR_OUT_OF_MEMORY; } else { _mem_set_type(RTCS_data_ptr, MEM_TYPE_RTCS_DATA); RTCS_set_data(RTCS_data_ptr); /* ** Initialize socket state */ socket_cfg_ptr = RTCS_mem_alloc_system_zero(sizeof(SOCKET_CONFIG_STRUCT)); if (socket_cfg_ptr == NULL) { error = RTCSERR_OUT_OF_MEMORY; } else { _mem_set_type(socket_cfg_ptr, MEM_TYPE_SOCKET_CONFIG_STRUCT); socket_cfg_ptr->INITIALIZED = TRUE; socket_cfg_ptr->SOCKET_HEAD = NULL; socket_cfg_ptr->SOCKET_TAIL = NULL; RTCS_mutex_init(&socket_cfg_ptr->SOCK_MUTEX); RTCS_setcfg(SOCKET, socket_cfg_ptr); /* ** Initialize global data */ _IP_forward = FALSE; _TCP_bypass_rx = FALSE; _TCP_bypass_tx = FALSE; RTCS_data_ptr->VERSION = RTCS_VERSION; #if RTCSCFG_LOG_SOCKET_API||RTCSCFG_LOG_PCB RTCS_data_ptr->RTCS_LOG_PROTCOUNT = RTCSLOG_PROT_MAX; RTCSLOG_disable(RTCS_LOGCTRL_ALL); #endif RTCS_data_ptr->TCPIP_qid = RTCS_msgq_get_id(0,TCPIP_QUEUE); /* ** Create a pool of buffers for use in communicating to the TCP/IP task. */ RTCS_data_ptr->TCPIP_msg_pool = RTCS_msgpool_create(sizeof(TCPIP_MESSAGE), _RTCS_msgpool_init, _RTCS_msgpool_grow, _RTCS_msgpool_max); if (RTCS_data_ptr->TCPIP_msg_pool == MSGPOOL_NULL_POOL_ID) { RTCS_log_error( ERROR_TCPIP, RTCSERR_CREATE_POOL_FAILED, 0, 0, 0); error = RTCSERR_CREATE_POOL_FAILED; } else { /* ** Create the socket partition */ RTCS_data_ptr->RTCS_socket_partition = RTCS_part_create(sizeof(SOCKET_STRUCT), _RTCS_socket_part_init, _RTCS_socket_part_grow, _RTCS_socket_part_max, NULL, NULL); if (RTCS_data_ptr->RTCS_socket_partition == 0) { RTCS_log_error(ERROR_RTCS, RTCSERR_CREATE_PARTITION_FAILED, 0, 0, 0); error = RTCSERR_CREATE_PARTITION_FAILED; } else { /* ** Create TCPIP task */ error = RTCS_task_create("TCP/IP", _RTCSTASK_priority, _RTCSTASK_stacksize, TCPIP_task, NULL); if (error) { RTCS_part_destroy(RTCS_data_ptr->RTCS_socket_partition); } } if (error) { RTCS_msgpool_destroy( RTCS_data_ptr->TCPIP_msg_pool ); } } if (error) { RTCS_setcfg(SOCKET, NULL); _mem_free(socket_cfg_ptr); } } if (error) { RTCS_set_data(NULL); _mem_free(RTCS_data_ptr); } } return error; } /* Endbody */