Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
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 Sun Jul 17 2022 08:25:28 by 1.7.2