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.
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 Tue Jul 12 2022 14:24:29 by
