This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

source: ps/trunk/build/premake/premake5/contrib/mbedtls/library/net.c

Last change on this file was 20366, checked in by Itms, 7 years ago

Alpha 12 version of Premake 5, including prebuilt binary for Windows.
Directly taken from https://premake.github.io/.

Refs #3729.

File size: 14.8 KB
Line 
1/*
2 * TCP/IP or UDP/IP networking functions
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22#if !defined(MBEDTLS_CONFIG_FILE)
23#include "mbedtls/config.h"
24#else
25#include MBEDTLS_CONFIG_FILE
26#endif
27
28#if defined(MBEDTLS_NET_C)
29
30#include "mbedtls/net.h"
31
32#include <string.h>
33
34#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
35 !defined(EFI32)
36
37#ifdef _WIN32_WINNT
38#undef _WIN32_WINNT
39#endif
40/* Enables getaddrinfo() & Co */
41#define _WIN32_WINNT 0x0501
42#include <ws2tcpip.h>
43
44#include <winsock2.h>
45#include <windows.h>
46
47#if defined(_MSC_VER)
48#if defined(_WIN32_WCE)
49#pragma comment( lib, "ws2.lib" )
50#else
51#pragma comment( lib, "ws2_32.lib" )
52#endif
53#endif /* _MSC_VER */
54
55#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
56#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
57#define close(fd) closesocket(fd)
58
59static int wsa_init_done = 0;
60
61#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
62
63#include <sys/types.h>
64#include <sys/socket.h>
65#include <netinet/in.h>
66#include <arpa/inet.h>
67#include <sys/time.h>
68#include <unistd.h>
69#include <signal.h>
70#include <fcntl.h>
71#include <netdb.h>
72#include <errno.h>
73
74#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
75
76/* Some MS functions want int and MSVC warns if we pass size_t,
77 * but the standard fucntions use socklen_t, so cast only for MSVC */
78#if defined(_MSC_VER)
79#define MSVC_INT_CAST (int)
80#else
81#define MSVC_INT_CAST
82#endif
83
84#include <stdlib.h>
85#include <stdio.h>
86
87#include <time.h>
88
89#include <stdint.h>
90
91/*
92 * Prepare for using the sockets interface
93 */
94static int net_prepare( void )
95{
96#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
97 !defined(EFI32)
98 WSADATA wsaData;
99
100 if( wsa_init_done == 0 )
101 {
102 if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
103 return( MBEDTLS_ERR_NET_SOCKET_FAILED );
104
105 wsa_init_done = 1;
106 }
107#else
108#if !defined(EFIX64) && !defined(EFI32)
109 signal( SIGPIPE, SIG_IGN );
110#endif
111#endif
112 return( 0 );
113}
114
115/*
116 * Initialize a context
117 */
118void mbedtls_net_init( mbedtls_net_context *ctx )
119{
120 ctx->fd = -1;
121}
122
123/*
124 * Initiate a TCP connection with host:port and the given protocol
125 */
126int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
127{
128 int ret;
129 struct addrinfo hints, *addr_list, *cur;
130
131 if( ( ret = net_prepare() ) != 0 )
132 return( ret );
133
134 /* Do name resolution with both IPv6 and IPv4 */
135 memset( &hints, 0, sizeof( hints ) );
136 hints.ai_family = AF_UNSPEC;
137 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
138 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
139
140 if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
141 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
142
143 /* Try the sockaddrs until a connection succeeds */
144 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
145 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
146 {
147 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
148 cur->ai_protocol );
149 if( ctx->fd < 0 )
150 {
151 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
152 continue;
153 }
154
155 if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
156 {
157 ret = 0;
158 break;
159 }
160
161 close( ctx->fd );
162 ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
163 }
164
165 freeaddrinfo( addr_list );
166
167 return( ret );
168}
169
170/*
171 * Create a listening socket on bind_ip:port
172 */
173int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
174{
175 int n, ret;
176 struct addrinfo hints, *addr_list, *cur;
177
178 if( ( ret = net_prepare() ) != 0 )
179 return( ret );
180
181 /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
182 memset( &hints, 0, sizeof( hints ) );
183 hints.ai_family = AF_UNSPEC;
184 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
185 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
186 if( bind_ip == NULL )
187 hints.ai_flags = AI_PASSIVE;
188
189 if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
190 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
191
192 /* Try the sockaddrs until a binding succeeds */
193 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
194 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
195 {
196 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
197 cur->ai_protocol );
198 if( ctx->fd < 0 )
199 {
200 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
201 continue;
202 }
203
204 n = 1;
205 if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
206 (const char *) &n, sizeof( n ) ) != 0 )
207 {
208 close( ctx->fd );
209 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
210 continue;
211 }
212
213 if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
214 {
215 close( ctx->fd );
216 ret = MBEDTLS_ERR_NET_BIND_FAILED;
217 continue;
218 }
219
220 /* Listen only makes sense for TCP */
221 if( proto == MBEDTLS_NET_PROTO_TCP )
222 {
223 if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
224 {
225 close( ctx->fd );
226 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
227 continue;
228 }
229 }
230
231 /* I we ever get there, it's a success */
232 ret = 0;
233 break;
234 }
235
236 freeaddrinfo( addr_list );
237
238 return( ret );
239
240}
241
242#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
243 !defined(EFI32)
244/*
245 * Check if the requested operation would be blocking on a non-blocking socket
246 * and thus 'failed' with a negative return value.
247 */
248static int net_would_block( const mbedtls_net_context *ctx )
249{
250 ((void) ctx);
251 return( WSAGetLastError() == WSAEWOULDBLOCK );
252}
253#else
254/*
255 * Check if the requested operation would be blocking on a non-blocking socket
256 * and thus 'failed' with a negative return value.
257 *
258 * Note: on a blocking socket this function always returns 0!
259 */
260static int net_would_block( const mbedtls_net_context *ctx )
261{
262 /*
263 * Never return 'WOULD BLOCK' on a non-blocking socket
264 */
265 if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
266 return( 0 );
267
268 switch( errno )
269 {
270#if defined EAGAIN
271 case EAGAIN:
272#endif
273#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
274 case EWOULDBLOCK:
275#endif
276 return( 1 );
277 }
278 return( 0 );
279}
280#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
281
282/*
283 * Accept a connection from a remote client
284 */
285int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
286 mbedtls_net_context *client_ctx,
287 void *client_ip, size_t buf_size, size_t *ip_len )
288{
289 int ret;
290 int type;
291
292 struct sockaddr_storage client_addr;
293
294#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
295 defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t)
296 socklen_t n = (socklen_t) sizeof( client_addr );
297 socklen_t type_len = (socklen_t) sizeof( type );
298#else
299 int n = (int) sizeof( client_addr );
300 int type_len = (int) sizeof( type );
301#endif
302
303 /* Is this a TCP or UDP socket? */
304 if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
305 (void *) &type, &type_len ) != 0 ||
306 ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
307 {
308 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
309 }
310
311 if( type == SOCK_STREAM )
312 {
313 /* TCP: actual accept() */
314 ret = client_ctx->fd = (int) accept( bind_ctx->fd,
315 (struct sockaddr *) &client_addr, &n );
316 }
317 else
318 {
319 /* UDP: wait for a message, but keep it in the queue */
320 char buf[1] = { 0 };
321
322 ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
323 (struct sockaddr *) &client_addr, &n );
324
325#if defined(_WIN32)
326 if( ret == SOCKET_ERROR &&
327 WSAGetLastError() == WSAEMSGSIZE )
328 {
329 /* We know buf is too small, thanks, just peeking here */
330 ret = 0;
331 }
332#endif
333 }
334
335 if( ret < 0 )
336 {
337 if( net_would_block( bind_ctx ) != 0 )
338 return( MBEDTLS_ERR_SSL_WANT_READ );
339
340 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
341 }
342
343 /* UDP: hijack the listening socket to communicate with the client,
344 * then bind a new socket to accept new connections */
345 if( type != SOCK_STREAM )
346 {
347 struct sockaddr_storage local_addr;
348 int one = 1;
349
350 if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
351 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
352
353 client_ctx->fd = bind_ctx->fd;
354 bind_ctx->fd = -1; /* In case we exit early */
355
356 n = sizeof( struct sockaddr_storage );
357 if( getsockname( client_ctx->fd,
358 (struct sockaddr *) &local_addr, &n ) != 0 ||
359 ( bind_ctx->fd = (int) socket( local_addr.ss_family,
360 SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
361 setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
362 (const char *) &one, sizeof( one ) ) != 0 )
363 {
364 return( MBEDTLS_ERR_NET_SOCKET_FAILED );
365 }
366
367 if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
368 {
369 return( MBEDTLS_ERR_NET_BIND_FAILED );
370 }
371 }
372
373 if( client_ip != NULL )
374 {
375 if( client_addr.ss_family == AF_INET )
376 {
377 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
378 *ip_len = sizeof( addr4->sin_addr.s_addr );
379
380 if( buf_size < *ip_len )
381 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
382
383 memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
384 }
385 else
386 {
387 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
388 *ip_len = sizeof( addr6->sin6_addr.s6_addr );
389
390 if( buf_size < *ip_len )
391 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
392
393 memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
394 }
395 }
396
397 return( 0 );
398}
399
400/*
401 * Set the socket blocking or non-blocking
402 */
403int mbedtls_net_set_block( mbedtls_net_context *ctx )
404{
405#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
406 !defined(EFI32)
407 u_long n = 0;
408 return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
409#else
410 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
411#endif
412}
413
414int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
415{
416#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
417 !defined(EFI32)
418 u_long n = 1;
419 return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
420#else
421 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
422#endif
423}
424
425/*
426 * Portable usleep helper
427 */
428void mbedtls_net_usleep( unsigned long usec )
429{
430#if defined(_WIN32)
431 Sleep( ( usec + 999 ) / 1000 );
432#else
433 struct timeval tv;
434 tv.tv_sec = usec / 1000000;
435#if defined(__unix__) || defined(__unix) || \
436 ( defined(__APPLE__) && defined(__MACH__) )
437 tv.tv_usec = (suseconds_t) usec % 1000000;
438#else
439 tv.tv_usec = usec % 1000000;
440#endif
441 select( 0, NULL, NULL, NULL, &tv );
442#endif
443}
444
445/*
446 * Read at most 'len' characters
447 */
448int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
449{
450 int ret;
451 int fd = ((mbedtls_net_context *) ctx)->fd;
452
453 if( fd < 0 )
454 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
455
456 ret = (int) read( fd, buf, len );
457
458 if( ret < 0 )
459 {
460 if( net_would_block( ctx ) != 0 )
461 return( MBEDTLS_ERR_SSL_WANT_READ );
462
463#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
464 !defined(EFI32)
465 if( WSAGetLastError() == WSAECONNRESET )
466 return( MBEDTLS_ERR_NET_CONN_RESET );
467#else
468 if( errno == EPIPE || errno == ECONNRESET )
469 return( MBEDTLS_ERR_NET_CONN_RESET );
470
471 if( errno == EINTR )
472 return( MBEDTLS_ERR_SSL_WANT_READ );
473#endif
474
475 return( MBEDTLS_ERR_NET_RECV_FAILED );
476 }
477
478 return( ret );
479}
480
481/*
482 * Read at most 'len' characters, blocking for at most 'timeout' ms
483 */
484int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
485 uint32_t timeout )
486{
487 int ret;
488 struct timeval tv;
489 fd_set read_fds;
490 int fd = ((mbedtls_net_context *) ctx)->fd;
491
492 if( fd < 0 )
493 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
494
495 FD_ZERO( &read_fds );
496 FD_SET( fd, &read_fds );
497
498 tv.tv_sec = timeout / 1000;
499 tv.tv_usec = ( timeout % 1000 ) * 1000;
500
501 ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
502
503 /* Zero fds ready means we timed out */
504 if( ret == 0 )
505 return( MBEDTLS_ERR_SSL_TIMEOUT );
506
507 if( ret < 0 )
508 {
509#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
510 !defined(EFI32)
511 if( WSAGetLastError() == WSAEINTR )
512 return( MBEDTLS_ERR_SSL_WANT_READ );
513#else
514 if( errno == EINTR )
515 return( MBEDTLS_ERR_SSL_WANT_READ );
516#endif
517
518 return( MBEDTLS_ERR_NET_RECV_FAILED );
519 }
520
521 /* This call will not block */
522 return( mbedtls_net_recv( ctx, buf, len ) );
523}
524
525/*
526 * Write at most 'len' characters
527 */
528int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
529{
530 int ret;
531 int fd = ((mbedtls_net_context *) ctx)->fd;
532
533 if( fd < 0 )
534 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
535
536 ret = (int) write( fd, buf, len );
537
538 if( ret < 0 )
539 {
540 if( net_would_block( ctx ) != 0 )
541 return( MBEDTLS_ERR_SSL_WANT_WRITE );
542
543#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
544 !defined(EFI32)
545 if( WSAGetLastError() == WSAECONNRESET )
546 return( MBEDTLS_ERR_NET_CONN_RESET );
547#else
548 if( errno == EPIPE || errno == ECONNRESET )
549 return( MBEDTLS_ERR_NET_CONN_RESET );
550
551 if( errno == EINTR )
552 return( MBEDTLS_ERR_SSL_WANT_WRITE );
553#endif
554
555 return( MBEDTLS_ERR_NET_SEND_FAILED );
556 }
557
558 return( ret );
559}
560
561/*
562 * Gracefully close the connection
563 */
564void mbedtls_net_free( mbedtls_net_context *ctx )
565{
566 if( ctx->fd == -1 )
567 return;
568
569 shutdown( ctx->fd, 2 );
570 close( ctx->fd );
571
572 ctx->fd = -1;
573}
574
575#endif /* MBEDTLS_NET_C */
Note: See TracBrowser for help on using the repository browser.