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 mbed-os 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, const char *port, int proto ) 00137 { 00138 int ret; 00139 struct addrinfo hints, *addr_list, *cur; 00140 00141 if( ( ret = net_prepare() ) != 0 ) 00142 return( ret ); 00143 00144 /* Do name resolution with both IPv6 and IPv4 */ 00145 memset( &hints, 0, sizeof( hints ) ); 00146 hints.ai_family = AF_UNSPEC; 00147 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 00148 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; 00149 00150 if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) 00151 return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); 00152 00153 /* Try the sockaddrs until a connection succeeds */ 00154 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; 00155 for( cur = addr_list; cur != NULL; cur = cur->ai_next ) 00156 { 00157 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, 00158 cur->ai_protocol ); 00159 if( ctx->fd < 0 ) 00160 { 00161 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00162 continue; 00163 } 00164 00165 if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) 00166 { 00167 ret = 0; 00168 break; 00169 } 00170 00171 close( ctx->fd ); 00172 ret = MBEDTLS_ERR_NET_CONNECT_FAILED; 00173 } 00174 00175 freeaddrinfo( addr_list ); 00176 00177 return( ret ); 00178 } 00179 00180 /* 00181 * Create a listening socket on bind_ip:port 00182 */ 00183 int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) 00184 { 00185 int n, ret; 00186 struct addrinfo hints, *addr_list, *cur; 00187 00188 if( ( ret = net_prepare() ) != 0 ) 00189 return( ret ); 00190 00191 /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ 00192 memset( &hints, 0, sizeof( hints ) ); 00193 hints.ai_family = AF_UNSPEC; 00194 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 00195 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; 00196 if( bind_ip == NULL ) 00197 hints.ai_flags = AI_PASSIVE; 00198 00199 if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) 00200 return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); 00201 00202 /* Try the sockaddrs until a binding succeeds */ 00203 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; 00204 for( cur = addr_list; cur != NULL; cur = cur->ai_next ) 00205 { 00206 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, 00207 cur->ai_protocol ); 00208 if( ctx->fd < 0 ) 00209 { 00210 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00211 continue; 00212 } 00213 00214 n = 1; 00215 if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, 00216 (const char *) &n, sizeof( n ) ) != 0 ) 00217 { 00218 close( ctx->fd ); 00219 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00220 continue; 00221 } 00222 00223 if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) 00224 { 00225 close( ctx->fd ); 00226 ret = MBEDTLS_ERR_NET_BIND_FAILED; 00227 continue; 00228 } 00229 00230 /* Listen only makes sense for TCP */ 00231 if( proto == MBEDTLS_NET_PROTO_TCP ) 00232 { 00233 if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) 00234 { 00235 close( ctx->fd ); 00236 ret = MBEDTLS_ERR_NET_LISTEN_FAILED; 00237 continue; 00238 } 00239 } 00240 00241 /* I we ever get there, it's a success */ 00242 ret = 0; 00243 break; 00244 } 00245 00246 freeaddrinfo( addr_list ); 00247 00248 return( ret ); 00249 00250 } 00251 00252 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00253 !defined(EFI32) 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 static int net_would_block( const mbedtls_net_context *ctx ) 00259 { 00260 ((void) ctx); 00261 return( WSAGetLastError() == WSAEWOULDBLOCK ); 00262 } 00263 #else 00264 /* 00265 * Check if the requested operation would be blocking on a non-blocking socket 00266 * and thus 'failed' with a negative return value. 00267 * 00268 * Note: on a blocking socket this function always returns 0! 00269 */ 00270 static int net_would_block( const mbedtls_net_context *ctx ) 00271 { 00272 /* 00273 * Never return 'WOULD BLOCK' on a non-blocking socket 00274 */ 00275 if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) 00276 return( 0 ); 00277 00278 switch( errno ) 00279 { 00280 #if defined EAGAIN 00281 case EAGAIN: 00282 #endif 00283 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN 00284 case EWOULDBLOCK: 00285 #endif 00286 return( 1 ); 00287 } 00288 return( 0 ); 00289 } 00290 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ 00291 00292 /* 00293 * Accept a connection from a remote client 00294 */ 00295 int mbedtls_net_accept( mbedtls_net_context *bind_ctx, 00296 mbedtls_net_context *client_ctx, 00297 void *client_ip, size_t buf_size, size_t *ip_len ) 00298 { 00299 int ret; 00300 int type; 00301 00302 struct sockaddr_storage client_addr; 00303 00304 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ 00305 defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) 00306 socklen_t n = (socklen_t) sizeof( client_addr ); 00307 socklen_t type_len = (socklen_t) sizeof( type ); 00308 #else 00309 int n = (int) sizeof( client_addr ); 00310 int type_len = (int) sizeof( type ); 00311 #endif 00312 00313 /* Is this a TCP or UDP socket? */ 00314 if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, 00315 (void *) &type, &type_len ) != 0 || 00316 ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) 00317 { 00318 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00319 } 00320 00321 if( type == SOCK_STREAM ) 00322 { 00323 /* TCP: actual accept() */ 00324 ret = client_ctx->fd = (int) accept( bind_ctx->fd, 00325 (struct sockaddr *) &client_addr, &n ); 00326 } 00327 else 00328 { 00329 /* UDP: wait for a message, but keep it in the queue */ 00330 char buf[1] = { 0 }; 00331 00332 ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, 00333 (struct sockaddr *) &client_addr, &n ); 00334 00335 #if defined(_WIN32) 00336 if( ret == SOCKET_ERROR && 00337 WSAGetLastError() == WSAEMSGSIZE ) 00338 { 00339 /* We know buf is too small, thanks, just peeking here */ 00340 ret = 0; 00341 } 00342 #endif 00343 } 00344 00345 if( ret < 0 ) 00346 { 00347 if( net_would_block( bind_ctx ) != 0 ) 00348 return( MBEDTLS_ERR_SSL_WANT_READ ); 00349 00350 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00351 } 00352 00353 /* UDP: hijack the listening socket to communicate with the client, 00354 * then bind a new socket to accept new connections */ 00355 if( type != SOCK_STREAM ) 00356 { 00357 struct sockaddr_storage local_addr; 00358 int one = 1; 00359 00360 if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) 00361 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00362 00363 client_ctx->fd = bind_ctx->fd; 00364 bind_ctx->fd = -1; /* In case we exit early */ 00365 00366 n = sizeof( struct sockaddr_storage ); 00367 if( getsockname( client_ctx->fd, 00368 (struct sockaddr *) &local_addr, &n ) != 0 || 00369 ( bind_ctx->fd = (int) socket( local_addr.ss_family, 00370 SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || 00371 setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, 00372 (const char *) &one, sizeof( one ) ) != 0 ) 00373 { 00374 return( MBEDTLS_ERR_NET_SOCKET_FAILED ); 00375 } 00376 00377 if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) 00378 { 00379 return( MBEDTLS_ERR_NET_BIND_FAILED ); 00380 } 00381 } 00382 00383 if( client_ip != NULL ) 00384 { 00385 if( client_addr.ss_family == AF_INET ) 00386 { 00387 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; 00388 *ip_len = sizeof( addr4->sin_addr.s_addr ); 00389 00390 if( buf_size < *ip_len ) 00391 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); 00392 00393 memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); 00394 } 00395 else 00396 { 00397 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; 00398 *ip_len = sizeof( addr6->sin6_addr.s6_addr ); 00399 00400 if( buf_size < *ip_len ) 00401 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); 00402 00403 memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); 00404 } 00405 } 00406 00407 return( 0 ); 00408 } 00409 00410 /* 00411 * Set the socket blocking or non-blocking 00412 */ 00413 int mbedtls_net_set_block( mbedtls_net_context *ctx ) 00414 { 00415 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00416 !defined(EFI32) 00417 u_long n = 0; 00418 return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); 00419 #else 00420 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); 00421 #endif 00422 } 00423 00424 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) 00425 { 00426 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00427 !defined(EFI32) 00428 u_long n = 1; 00429 return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); 00430 #else 00431 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); 00432 #endif 00433 } 00434 00435 /* 00436 * Portable usleep helper 00437 */ 00438 void mbedtls_net_usleep( unsigned long usec ) 00439 { 00440 #if defined(_WIN32) 00441 Sleep( ( usec + 999 ) / 1000 ); 00442 #else 00443 struct timeval tv; 00444 tv.tv_sec = usec / 1000000; 00445 #if defined(__unix__) || defined(__unix) || \ 00446 ( defined(__APPLE__) && defined(__MACH__) ) 00447 tv.tv_usec = (suseconds_t) usec % 1000000; 00448 #else 00449 tv.tv_usec = usec % 1000000; 00450 #endif 00451 select( 0, NULL, NULL, NULL, &tv ); 00452 #endif 00453 } 00454 00455 /* 00456 * Read at most 'len' characters 00457 */ 00458 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) 00459 { 00460 int ret; 00461 int fd = ((mbedtls_net_context *) ctx)->fd; 00462 00463 if( fd < 0 ) 00464 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00465 00466 ret = (int) read( fd, buf, len ); 00467 00468 if( ret < 0 ) 00469 { 00470 if( net_would_block( ctx ) != 0 ) 00471 return( MBEDTLS_ERR_SSL_WANT_READ ); 00472 00473 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00474 !defined(EFI32) 00475 if( WSAGetLastError() == WSAECONNRESET ) 00476 return( MBEDTLS_ERR_NET_CONN_RESET ); 00477 #else 00478 if( errno == EPIPE || errno == ECONNRESET ) 00479 return( MBEDTLS_ERR_NET_CONN_RESET ); 00480 00481 if( errno == EINTR ) 00482 return( MBEDTLS_ERR_SSL_WANT_READ ); 00483 #endif 00484 00485 return( MBEDTLS_ERR_NET_RECV_FAILED ); 00486 } 00487 00488 return( ret ); 00489 } 00490 00491 /* 00492 * Read at most 'len' characters, blocking for at most 'timeout' ms 00493 */ 00494 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, 00495 uint32_t timeout ) 00496 { 00497 int ret; 00498 struct timeval tv; 00499 fd_set read_fds; 00500 int fd = ((mbedtls_net_context *) ctx)->fd; 00501 00502 if( fd < 0 ) 00503 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00504 00505 FD_ZERO( &read_fds ); 00506 FD_SET( fd, &read_fds ); 00507 00508 tv.tv_sec = timeout / 1000; 00509 tv.tv_usec = ( timeout % 1000 ) * 1000; 00510 00511 ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); 00512 00513 /* Zero fds ready means we timed out */ 00514 if( ret == 0 ) 00515 return( MBEDTLS_ERR_SSL_TIMEOUT ); 00516 00517 if( ret < 0 ) 00518 { 00519 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00520 !defined(EFI32) 00521 if( WSAGetLastError() == WSAEINTR ) 00522 return( MBEDTLS_ERR_SSL_WANT_READ ); 00523 #else 00524 if( errno == EINTR ) 00525 return( MBEDTLS_ERR_SSL_WANT_READ ); 00526 #endif 00527 00528 return( MBEDTLS_ERR_NET_RECV_FAILED ); 00529 } 00530 00531 /* This call will not block */ 00532 return( mbedtls_net_recv( ctx, buf, len ) ); 00533 } 00534 00535 /* 00536 * Write at most 'len' characters 00537 */ 00538 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) 00539 { 00540 int ret; 00541 int fd = ((mbedtls_net_context *) ctx)->fd; 00542 00543 if( fd < 0 ) 00544 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00545 00546 ret = (int) write( fd, buf, len ); 00547 00548 if( ret < 0 ) 00549 { 00550 if( net_would_block( ctx ) != 0 ) 00551 return( MBEDTLS_ERR_SSL_WANT_WRITE ); 00552 00553 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00554 !defined(EFI32) 00555 if( WSAGetLastError() == WSAECONNRESET ) 00556 return( MBEDTLS_ERR_NET_CONN_RESET ); 00557 #else 00558 if( errno == EPIPE || errno == ECONNRESET ) 00559 return( MBEDTLS_ERR_NET_CONN_RESET ); 00560 00561 if( errno == EINTR ) 00562 return( MBEDTLS_ERR_SSL_WANT_WRITE ); 00563 #endif 00564 00565 return( MBEDTLS_ERR_NET_SEND_FAILED ); 00566 } 00567 00568 return( ret ); 00569 } 00570 00571 /* 00572 * Gracefully close the connection 00573 */ 00574 void mbedtls_net_free( mbedtls_net_context *ctx ) 00575 { 00576 if( ctx->fd == -1 ) 00577 return; 00578 00579 shutdown( ctx->fd, 2 ); 00580 close( ctx->fd ); 00581 00582 ctx->fd = -1; 00583 } 00584 00585 #endif /* MBEDTLS_NET_C */
Generated on Tue Jul 12 2022 13:16:00 by
