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.
Fork of OmniWheels by
net_sockets.c
00001 /* 00002 * TCP/IP or UDP/IP networking functions 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 00022 #if !defined(MBEDTLS_CONFIG_FILE) 00023 #include "mbedtls/config.h" 00024 #else 00025 #include MBEDTLS_CONFIG_FILE 00026 #endif 00027 00028 #if defined(MBEDTLS_NET_C) 00029 00030 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ 00031 !defined(__APPLE__) && !defined(_WIN32) 00032 #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" 00033 #endif 00034 00035 #if defined(MBEDTLS_PLATFORM_C) 00036 #include "mbedtls/platform.h" 00037 #else 00038 #include <stdlib.h> 00039 #endif 00040 00041 #include "mbedtls/net_sockets.h" 00042 00043 #include <string.h> 00044 00045 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ 00046 !defined(EFI32) 00047 00048 #ifdef _WIN32_WINNT 00049 #undef _WIN32_WINNT 00050 #endif 00051 /* Enables getaddrinfo() & Co */ 00052 #define _WIN32_WINNT 0x0501 00053 #include <ws2tcpip.h> 00054 00055 #include <winsock2.h> 00056 #include <windows.h> 00057 00058 #if defined(_MSC_VER) 00059 #if defined(_WIN32_WCE) 00060 #pragma comment( lib, "ws2.lib" ) 00061 #else 00062 #pragma comment( lib, "ws2_32.lib" ) 00063 #endif 00064 #endif /* _MSC_VER */ 00065 00066 #define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) 00067 #define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) 00068 #define close(fd) closesocket(fd) 00069 00070 static int wsa_init_done = 0; 00071 00072 #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ 00073 00074 #include <sys/types.h> 00075 #include <sys/socket.h> 00076 #include <netinet/in.h> 00077 #include <arpa/inet.h> 00078 #include <sys/time.h> 00079 #include <unistd.h> 00080 #include <signal.h> 00081 #include <fcntl.h> 00082 #include <netdb.h> 00083 #include <errno.h> 00084 00085 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ 00086 00087 /* Some MS functions want int and MSVC warns if we pass size_t, 00088 * but the standard functions use socklen_t, so cast only for MSVC */ 00089 #if defined(_MSC_VER) 00090 #define MSVC_INT_CAST (int) 00091 #else 00092 #define MSVC_INT_CAST 00093 #endif 00094 00095 #include <stdio.h> 00096 00097 #include <time.h> 00098 00099 #include <stdint.h> 00100 00101 /* 00102 * Prepare for using the sockets interface 00103 */ 00104 static int net_prepare( void ) 00105 { 00106 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00107 !defined(EFI32) 00108 WSADATA wsaData; 00109 00110 if( wsa_init_done == 0 ) 00111 { 00112 if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) 00113 return( MBEDTLS_ERR_NET_SOCKET_FAILED ); 00114 00115 wsa_init_done = 1; 00116 } 00117 #else 00118 #if !defined(EFIX64) && !defined(EFI32) 00119 signal( SIGPIPE, SIG_IGN ); 00120 #endif 00121 #endif 00122 return( 0 ); 00123 } 00124 00125 /* 00126 * Initialize a context 00127 */ 00128 void mbedtls_net_init( mbedtls_net_context *ctx ) 00129 { 00130 ctx->fd = -1; 00131 } 00132 00133 /* 00134 * Initiate a TCP connection with host:port and the given protocol 00135 */ 00136 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, 00137 const char *port, int proto ) 00138 { 00139 int ret; 00140 struct addrinfo hints, *addr_list, *cur; 00141 00142 if( ( ret = net_prepare() ) != 0 ) 00143 return( ret ); 00144 00145 /* Do name resolution with both IPv6 and IPv4 */ 00146 memset( &hints, 0, sizeof( hints ) ); 00147 hints.ai_family = AF_UNSPEC; 00148 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 00149 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; 00150 00151 if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) 00152 return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); 00153 00154 /* Try the sockaddrs until a connection succeeds */ 00155 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; 00156 for( cur = addr_list; cur != NULL; cur = cur->ai_next ) 00157 { 00158 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, 00159 cur->ai_protocol ); 00160 if( ctx->fd < 0 ) 00161 { 00162 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00163 continue; 00164 } 00165 00166 if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) 00167 { 00168 ret = 0; 00169 break; 00170 } 00171 00172 close( ctx->fd ); 00173 ret = MBEDTLS_ERR_NET_CONNECT_FAILED; 00174 } 00175 00176 freeaddrinfo( addr_list ); 00177 00178 return( ret ); 00179 } 00180 00181 /* 00182 * Create a listening socket on bind_ip:port 00183 */ 00184 int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) 00185 { 00186 int n, ret; 00187 struct addrinfo hints, *addr_list, *cur; 00188 00189 if( ( ret = net_prepare() ) != 0 ) 00190 return( ret ); 00191 00192 /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ 00193 memset( &hints, 0, sizeof( hints ) ); 00194 hints.ai_family = AF_UNSPEC; 00195 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 00196 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; 00197 if( bind_ip == NULL ) 00198 hints.ai_flags = AI_PASSIVE; 00199 00200 if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) 00201 return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); 00202 00203 /* Try the sockaddrs until a binding succeeds */ 00204 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; 00205 for( cur = addr_list; cur != NULL; cur = cur->ai_next ) 00206 { 00207 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, 00208 cur->ai_protocol ); 00209 if( ctx->fd < 0 ) 00210 { 00211 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00212 continue; 00213 } 00214 00215 n = 1; 00216 if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, 00217 (const char *) &n, sizeof( n ) ) != 0 ) 00218 { 00219 close( ctx->fd ); 00220 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00221 continue; 00222 } 00223 00224 if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) 00225 { 00226 close( ctx->fd ); 00227 ret = MBEDTLS_ERR_NET_BIND_FAILED; 00228 continue; 00229 } 00230 00231 /* Listen only makes sense for TCP */ 00232 if( proto == MBEDTLS_NET_PROTO_TCP ) 00233 { 00234 if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) 00235 { 00236 close( ctx->fd ); 00237 ret = MBEDTLS_ERR_NET_LISTEN_FAILED; 00238 continue; 00239 } 00240 } 00241 00242 /* Bind was successful */ 00243 ret = 0; 00244 break; 00245 } 00246 00247 freeaddrinfo( addr_list ); 00248 00249 return( ret ); 00250 00251 } 00252 00253 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00254 !defined(EFI32) 00255 /* 00256 * Check if the requested operation would be blocking on a non-blocking socket 00257 * and thus 'failed' with a negative return value. 00258 */ 00259 static int net_would_block( const mbedtls_net_context *ctx ) 00260 { 00261 ((void) ctx); 00262 return( WSAGetLastError() == WSAEWOULDBLOCK ); 00263 } 00264 #else 00265 /* 00266 * Check if the requested operation would be blocking on a non-blocking socket 00267 * and thus 'failed' with a negative return value. 00268 * 00269 * Note: on a blocking socket this function always returns 0! 00270 */ 00271 static int net_would_block( const mbedtls_net_context *ctx ) 00272 { 00273 int err = errno; 00274 00275 /* 00276 * Never return 'WOULD BLOCK' on a non-blocking socket 00277 */ 00278 if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) 00279 { 00280 errno = err; 00281 return( 0 ); 00282 } 00283 00284 switch( errno = err ) 00285 { 00286 #if defined EAGAIN 00287 case EAGAIN: 00288 #endif 00289 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN 00290 case EWOULDBLOCK: 00291 #endif 00292 return( 1 ); 00293 } 00294 return( 0 ); 00295 } 00296 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ 00297 00298 /* 00299 * Accept a connection from a remote client 00300 */ 00301 int mbedtls_net_accept( mbedtls_net_context *bind_ctx, 00302 mbedtls_net_context *client_ctx, 00303 void *client_ip, size_t buf_size, size_t *ip_len ) 00304 { 00305 int ret; 00306 int type; 00307 00308 struct sockaddr_storage client_addr; 00309 00310 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ 00311 defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) 00312 socklen_t n = (socklen_t) sizeof( client_addr ); 00313 socklen_t type_len = (socklen_t) sizeof( type ); 00314 #else 00315 int n = (int) sizeof( client_addr ); 00316 int type_len = (int) sizeof( type ); 00317 #endif 00318 00319 /* Is this a TCP or UDP socket? */ 00320 if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, 00321 (void *) &type, &type_len ) != 0 || 00322 ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) 00323 { 00324 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00325 } 00326 00327 if( type == SOCK_STREAM ) 00328 { 00329 /* TCP: actual accept() */ 00330 ret = client_ctx->fd = (int) accept( bind_ctx->fd, 00331 (struct sockaddr *) &client_addr, &n ); 00332 } 00333 else 00334 { 00335 /* UDP: wait for a message, but keep it in the queue */ 00336 char buf[1] = { 0 }; 00337 00338 ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, 00339 (struct sockaddr *) &client_addr, &n ); 00340 00341 #if defined(_WIN32) 00342 if( ret == SOCKET_ERROR && 00343 WSAGetLastError() == WSAEMSGSIZE ) 00344 { 00345 /* We know buf is too small, thanks, just peeking here */ 00346 ret = 0; 00347 } 00348 #endif 00349 } 00350 00351 if( ret < 0 ) 00352 { 00353 if( net_would_block( bind_ctx ) != 0 ) 00354 return( MBEDTLS_ERR_SSL_WANT_READ ); 00355 00356 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00357 } 00358 00359 /* UDP: hijack the listening socket to communicate with the client, 00360 * then bind a new socket to accept new connections */ 00361 if( type != SOCK_STREAM ) 00362 { 00363 struct sockaddr_storage local_addr; 00364 int one = 1; 00365 00366 if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) 00367 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00368 00369 client_ctx->fd = bind_ctx->fd; 00370 bind_ctx->fd = -1; /* In case we exit early */ 00371 00372 n = sizeof( struct sockaddr_storage ); 00373 if( getsockname( client_ctx->fd, 00374 (struct sockaddr *) &local_addr, &n ) != 0 || 00375 ( bind_ctx->fd = (int) socket( local_addr.ss_family, 00376 SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || 00377 setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, 00378 (const char *) &one, sizeof( one ) ) != 0 ) 00379 { 00380 return( MBEDTLS_ERR_NET_SOCKET_FAILED ); 00381 } 00382 00383 if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) 00384 { 00385 return( MBEDTLS_ERR_NET_BIND_FAILED ); 00386 } 00387 } 00388 00389 if( client_ip != NULL ) 00390 { 00391 if( client_addr.ss_family == AF_INET ) 00392 { 00393 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; 00394 *ip_len = sizeof( addr4->sin_addr.s_addr ); 00395 00396 if( buf_size < *ip_len ) 00397 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); 00398 00399 memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); 00400 } 00401 else 00402 { 00403 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; 00404 *ip_len = sizeof( addr6->sin6_addr.s6_addr ); 00405 00406 if( buf_size < *ip_len ) 00407 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); 00408 00409 memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); 00410 } 00411 } 00412 00413 return( 0 ); 00414 } 00415 00416 /* 00417 * Set the socket blocking or non-blocking 00418 */ 00419 int mbedtls_net_set_block( mbedtls_net_context *ctx ) 00420 { 00421 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00422 !defined(EFI32) 00423 u_long n = 0; 00424 return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); 00425 #else 00426 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); 00427 #endif 00428 } 00429 00430 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) 00431 { 00432 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00433 !defined(EFI32) 00434 u_long n = 1; 00435 return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); 00436 #else 00437 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); 00438 #endif 00439 } 00440 00441 /* 00442 * Portable usleep helper 00443 */ 00444 void mbedtls_net_usleep( unsigned long usec ) 00445 { 00446 #if defined(_WIN32) 00447 Sleep( ( usec + 999 ) / 1000 ); 00448 #else 00449 struct timeval tv; 00450 tv.tv_sec = usec / 1000000; 00451 #if defined(__unix__) || defined(__unix) || \ 00452 ( defined(__APPLE__) && defined(__MACH__) ) 00453 tv.tv_usec = (suseconds_t) usec % 1000000; 00454 #else 00455 tv.tv_usec = usec % 1000000; 00456 #endif 00457 select( 0, NULL, NULL, NULL, &tv ); 00458 #endif 00459 } 00460 00461 /* 00462 * Read at most 'len' characters 00463 */ 00464 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) 00465 { 00466 int ret; 00467 int fd = ((mbedtls_net_context *) ctx)->fd; 00468 00469 if( fd < 0 ) 00470 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00471 00472 ret = (int) read( fd, buf, len ); 00473 00474 if( ret < 0 ) 00475 { 00476 if( net_would_block( ctx ) != 0 ) 00477 return( MBEDTLS_ERR_SSL_WANT_READ ); 00478 00479 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00480 !defined(EFI32) 00481 if( WSAGetLastError() == WSAECONNRESET ) 00482 return( MBEDTLS_ERR_NET_CONN_RESET ); 00483 #else 00484 if( errno == EPIPE || errno == ECONNRESET ) 00485 return( MBEDTLS_ERR_NET_CONN_RESET ); 00486 00487 if( errno == EINTR ) 00488 return( MBEDTLS_ERR_SSL_WANT_READ ); 00489 #endif 00490 00491 return( MBEDTLS_ERR_NET_RECV_FAILED ); 00492 } 00493 00494 return( ret ); 00495 } 00496 00497 /* 00498 * Read at most 'len' characters, blocking for at most 'timeout' ms 00499 */ 00500 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, 00501 uint32_t timeout ) 00502 { 00503 int ret; 00504 struct timeval tv; 00505 fd_set read_fds; 00506 int fd = ((mbedtls_net_context *) ctx)->fd; 00507 00508 if( fd < 0 ) 00509 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00510 00511 FD_ZERO( &read_fds ); 00512 FD_SET( fd, &read_fds ); 00513 00514 tv.tv_sec = timeout / 1000; 00515 tv.tv_usec = ( timeout % 1000 ) * 1000; 00516 00517 ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); 00518 00519 /* Zero fds ready means we timed out */ 00520 if( ret == 0 ) 00521 return( MBEDTLS_ERR_SSL_TIMEOUT ); 00522 00523 if( ret < 0 ) 00524 { 00525 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00526 !defined(EFI32) 00527 if( WSAGetLastError() == WSAEINTR ) 00528 return( MBEDTLS_ERR_SSL_WANT_READ ); 00529 #else 00530 if( errno == EINTR ) 00531 return( MBEDTLS_ERR_SSL_WANT_READ ); 00532 #endif 00533 00534 return( MBEDTLS_ERR_NET_RECV_FAILED ); 00535 } 00536 00537 /* This call will not block */ 00538 return( mbedtls_net_recv( ctx, buf, len ) ); 00539 } 00540 00541 /* 00542 * Write at most 'len' characters 00543 */ 00544 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) 00545 { 00546 int ret; 00547 int fd = ((mbedtls_net_context *) ctx)->fd; 00548 00549 if( fd < 0 ) 00550 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00551 00552 ret = (int) write( fd, buf, len ); 00553 00554 if( ret < 0 ) 00555 { 00556 if( net_would_block( ctx ) != 0 ) 00557 return( MBEDTLS_ERR_SSL_WANT_WRITE ); 00558 00559 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00560 !defined(EFI32) 00561 if( WSAGetLastError() == WSAECONNRESET ) 00562 return( MBEDTLS_ERR_NET_CONN_RESET ); 00563 #else 00564 if( errno == EPIPE || errno == ECONNRESET ) 00565 return( MBEDTLS_ERR_NET_CONN_RESET ); 00566 00567 if( errno == EINTR ) 00568 return( MBEDTLS_ERR_SSL_WANT_WRITE ); 00569 #endif 00570 00571 return( MBEDTLS_ERR_NET_SEND_FAILED ); 00572 } 00573 00574 return( ret ); 00575 } 00576 00577 /* 00578 * Gracefully close the connection 00579 */ 00580 void mbedtls_net_free( mbedtls_net_context *ctx ) 00581 { 00582 if( ctx->fd == -1 ) 00583 return; 00584 00585 shutdown( ctx->fd, 2 ); 00586 close( ctx->fd ); 00587 00588 ctx->fd = -1; 00589 } 00590 00591 #endif /* MBEDTLS_NET_C */
Generated on Fri Jul 22 2022 04:53:57 by
1.7.2
