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 mbedtls 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 fucntions 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 /* 00274 * Never return 'WOULD BLOCK' on a non-blocking socket 00275 */ 00276 if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) 00277 return( 0 ); 00278 00279 switch( errno ) 00280 { 00281 #if defined EAGAIN 00282 case EAGAIN: 00283 #endif 00284 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN 00285 case EWOULDBLOCK: 00286 #endif 00287 return( 1 ); 00288 } 00289 return( 0 ); 00290 } 00291 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ 00292 00293 /* 00294 * Accept a connection from a remote client 00295 */ 00296 int mbedtls_net_accept( mbedtls_net_context *bind_ctx, 00297 mbedtls_net_context *client_ctx, 00298 void *client_ip, size_t buf_size, size_t *ip_len ) 00299 { 00300 int ret; 00301 int type; 00302 00303 struct sockaddr_storage client_addr; 00304 00305 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ 00306 defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) 00307 socklen_t n = (socklen_t) sizeof( client_addr ); 00308 socklen_t type_len = (socklen_t) sizeof( type ); 00309 #else 00310 int n = (int) sizeof( client_addr ); 00311 int type_len = (int) sizeof( type ); 00312 #endif 00313 00314 /* Is this a TCP or UDP socket? */ 00315 if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, 00316 (void *) &type, &type_len ) != 0 || 00317 ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) 00318 { 00319 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00320 } 00321 00322 if( type == SOCK_STREAM ) 00323 { 00324 /* TCP: actual accept() */ 00325 ret = client_ctx->fd = (int) accept( bind_ctx->fd, 00326 (struct sockaddr *) &client_addr, &n ); 00327 } 00328 else 00329 { 00330 /* UDP: wait for a message, but keep it in the queue */ 00331 char buf[1] = { 0 }; 00332 00333 ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, 00334 (struct sockaddr *) &client_addr, &n ); 00335 00336 #if defined(_WIN32) 00337 if( ret == SOCKET_ERROR && 00338 WSAGetLastError() == WSAEMSGSIZE ) 00339 { 00340 /* We know buf is too small, thanks, just peeking here */ 00341 ret = 0; 00342 } 00343 #endif 00344 } 00345 00346 if( ret < 0 ) 00347 { 00348 if( net_would_block( bind_ctx ) != 0 ) 00349 return( MBEDTLS_ERR_SSL_WANT_READ ); 00350 00351 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00352 } 00353 00354 /* UDP: hijack the listening socket to communicate with the client, 00355 * then bind a new socket to accept new connections */ 00356 if( type != SOCK_STREAM ) 00357 { 00358 struct sockaddr_storage local_addr; 00359 int one = 1; 00360 00361 if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) 00362 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00363 00364 client_ctx->fd = bind_ctx->fd; 00365 bind_ctx->fd = -1; /* In case we exit early */ 00366 00367 n = sizeof( struct sockaddr_storage ); 00368 if( getsockname( client_ctx->fd, 00369 (struct sockaddr *) &local_addr, &n ) != 0 || 00370 ( bind_ctx->fd = (int) socket( local_addr.ss_family, 00371 SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || 00372 setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, 00373 (const char *) &one, sizeof( one ) ) != 0 ) 00374 { 00375 return( MBEDTLS_ERR_NET_SOCKET_FAILED ); 00376 } 00377 00378 if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) 00379 { 00380 return( MBEDTLS_ERR_NET_BIND_FAILED ); 00381 } 00382 } 00383 00384 if( client_ip != NULL ) 00385 { 00386 if( client_addr.ss_family == AF_INET ) 00387 { 00388 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; 00389 *ip_len = sizeof( addr4->sin_addr.s_addr ); 00390 00391 if( buf_size < *ip_len ) 00392 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); 00393 00394 memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); 00395 } 00396 else 00397 { 00398 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; 00399 *ip_len = sizeof( addr6->sin6_addr.s6_addr ); 00400 00401 if( buf_size < *ip_len ) 00402 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); 00403 00404 memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); 00405 } 00406 } 00407 00408 return( 0 ); 00409 } 00410 00411 /* 00412 * Set the socket blocking or non-blocking 00413 */ 00414 int mbedtls_net_set_block( mbedtls_net_context *ctx ) 00415 { 00416 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00417 !defined(EFI32) 00418 u_long n = 0; 00419 return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); 00420 #else 00421 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); 00422 #endif 00423 } 00424 00425 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) 00426 { 00427 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00428 !defined(EFI32) 00429 u_long n = 1; 00430 return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); 00431 #else 00432 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); 00433 #endif 00434 } 00435 00436 /* 00437 * Portable usleep helper 00438 */ 00439 void mbedtls_net_usleep( unsigned long usec ) 00440 { 00441 #if defined(_WIN32) 00442 Sleep( ( usec + 999 ) / 1000 ); 00443 #else 00444 struct timeval tv; 00445 tv.tv_sec = usec / 1000000; 00446 #if defined(__unix__) || defined(__unix) || \ 00447 ( defined(__APPLE__) && defined(__MACH__) ) 00448 tv.tv_usec = (suseconds_t) usec % 1000000; 00449 #else 00450 tv.tv_usec = usec % 1000000; 00451 #endif 00452 select( 0, NULL, NULL, NULL, &tv ); 00453 #endif 00454 } 00455 00456 /* 00457 * Read at most 'len' characters 00458 */ 00459 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) 00460 { 00461 int ret; 00462 int fd = ((mbedtls_net_context *) ctx)->fd; 00463 00464 if( fd < 0 ) 00465 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00466 00467 ret = (int) read( fd, buf, len ); 00468 00469 if( ret < 0 ) 00470 { 00471 if( net_would_block( ctx ) != 0 ) 00472 return( MBEDTLS_ERR_SSL_WANT_READ ); 00473 00474 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00475 !defined(EFI32) 00476 if( WSAGetLastError() == WSAECONNRESET ) 00477 return( MBEDTLS_ERR_NET_CONN_RESET ); 00478 #else 00479 if( errno == EPIPE || errno == ECONNRESET ) 00480 return( MBEDTLS_ERR_NET_CONN_RESET ); 00481 00482 if( errno == EINTR ) 00483 return( MBEDTLS_ERR_SSL_WANT_READ ); 00484 #endif 00485 00486 return( MBEDTLS_ERR_NET_RECV_FAILED ); 00487 } 00488 00489 return( ret ); 00490 } 00491 00492 /* 00493 * Read at most 'len' characters, blocking for at most 'timeout' ms 00494 */ 00495 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, 00496 uint32_t timeout ) 00497 { 00498 int ret; 00499 struct timeval tv; 00500 fd_set read_fds; 00501 int fd = ((mbedtls_net_context *) ctx)->fd; 00502 00503 if( fd < 0 ) 00504 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00505 00506 FD_ZERO( &read_fds ); 00507 FD_SET( fd, &read_fds ); 00508 00509 tv.tv_sec = timeout / 1000; 00510 tv.tv_usec = ( timeout % 1000 ) * 1000; 00511 00512 ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); 00513 00514 /* Zero fds ready means we timed out */ 00515 if( ret == 0 ) 00516 return( MBEDTLS_ERR_SSL_TIMEOUT ); 00517 00518 if( ret < 0 ) 00519 { 00520 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00521 !defined(EFI32) 00522 if( WSAGetLastError() == WSAEINTR ) 00523 return( MBEDTLS_ERR_SSL_WANT_READ ); 00524 #else 00525 if( errno == EINTR ) 00526 return( MBEDTLS_ERR_SSL_WANT_READ ); 00527 #endif 00528 00529 return( MBEDTLS_ERR_NET_RECV_FAILED ); 00530 } 00531 00532 /* This call will not block */ 00533 return( mbedtls_net_recv( ctx, buf, len ) ); 00534 } 00535 00536 /* 00537 * Write at most 'len' characters 00538 */ 00539 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) 00540 { 00541 int ret; 00542 int fd = ((mbedtls_net_context *) ctx)->fd; 00543 00544 if( fd < 0 ) 00545 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00546 00547 ret = (int) write( fd, buf, len ); 00548 00549 if( ret < 0 ) 00550 { 00551 if( net_would_block( ctx ) != 0 ) 00552 return( MBEDTLS_ERR_SSL_WANT_WRITE ); 00553 00554 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00555 !defined(EFI32) 00556 if( WSAGetLastError() == WSAECONNRESET ) 00557 return( MBEDTLS_ERR_NET_CONN_RESET ); 00558 #else 00559 if( errno == EPIPE || errno == ECONNRESET ) 00560 return( MBEDTLS_ERR_NET_CONN_RESET ); 00561 00562 if( errno == EINTR ) 00563 return( MBEDTLS_ERR_SSL_WANT_WRITE ); 00564 #endif 00565 00566 return( MBEDTLS_ERR_NET_SEND_FAILED ); 00567 } 00568 00569 return( ret ); 00570 } 00571 00572 /* 00573 * Gracefully close the connection 00574 */ 00575 void mbedtls_net_free( mbedtls_net_context *ctx ) 00576 { 00577 if( ctx->fd == -1 ) 00578 return; 00579 00580 shutdown( ctx->fd, 2 ); 00581 close( ctx->fd ); 00582 00583 ctx->fd = -1; 00584 } 00585 00586 #endif /* MBEDTLS_NET_C */
Generated on Tue Jul 12 2022 17:25:42 by
