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.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
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 11:02:47 by
