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