1 /*
2 * TCP/IP or UDP/IP networking functions
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 */
7
8 /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
9 * be set before config.h, which pulls in glibc's features.h indirectly.
10 * Harmless on other platforms. */
11 #ifndef _POSIX_C_SOURCE
12 #define _POSIX_C_SOURCE 200112L
13 #endif
14 #ifndef _XOPEN_SOURCE
15 #define _XOPEN_SOURCE 600 /* sockaddr_storage */
16 #endif
17
18 #include "common.h"
19
20 #if defined(MBEDTLS_NET_C)
21
22 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
23 !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
24 !defined(__HAIKU__) && !defined(__midipix__)
25 #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
26 #endif
27
28 #include "mbedtls/platform.h"
29
30 #include "mbedtls/net_sockets.h"
31 #include "mbedtls/error.h"
32
33 #include <string.h>
34
35 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
36 !defined(EFI32)
37
38 #define IS_EINTR(ret) ((ret) == WSAEINTR)
39
40 #if !defined(_WIN32_WINNT)
41 /* Enables getaddrinfo() & Co */
42 #define _WIN32_WINNT 0x0501
43 #endif
44
45 #include <ws2tcpip.h>
46
47 #include <winsock2.h>
48 #include <windows.h>
49 #if (_WIN32_WINNT < 0x0501)
50 #include <wspiapi.h>
51 #endif
52
53 #if defined(_MSC_VER)
54 #if defined(_WIN32_WCE)
55 #pragma comment( lib, "ws2.lib" )
56 #else
57 #pragma comment( lib, "ws2_32.lib" )
58 #endif
59 #endif /* _MSC_VER */
60
61 #define read(fd, buf, len) recv(fd, (char *) (buf), (int) (len), 0)
62 #define write(fd, buf, len) send(fd, (char *) (buf), (int) (len), 0)
63 #define close(fd) closesocket(fd)
64
65 static int wsa_init_done = 0;
66
67 #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
68
69 #include <sys/types.h>
70 #include <sys/socket.h>
71 #include <netinet/in.h>
72 #include <arpa/inet.h>
73 #include <sys/time.h>
74 #include <unistd.h>
75 #include <signal.h>
76 #include <fcntl.h>
77 #include <netdb.h>
78 #include <errno.h>
79
80 #define IS_EINTR(ret) ((ret) == EINTR)
81 #define SOCKET int
82
83 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
84
85 /* Some MS functions want int and MSVC warns if we pass size_t,
86 * but the standard functions use socklen_t, so cast only for MSVC */
87 #if defined(_MSC_VER)
88 #define MSVC_INT_CAST (int)
89 #else
90 #define MSVC_INT_CAST
91 #endif
92
93 #include <stdio.h>
94
95 #if defined(MBEDTLS_HAVE_TIME)
96 #include <time.h>
97 #endif
98
99 #include <stdint.h>
100
101 /*
102 * Prepare for using the sockets interface
103 */
net_prepare(void)104 static int net_prepare(void)
105 {
106 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
107 !defined(EFI32)
108 WSADATA wsaData;
109
110 if (wsa_init_done == 0) {
111 if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
112 return MBEDTLS_ERR_NET_SOCKET_FAILED;
113 }
114
115 wsa_init_done = 1;
116 }
117 #else
118 #if !defined(EFIX64) && !defined(EFI32)
119 signal(SIGPIPE, SIG_IGN);
120 #endif
121 #endif
122 return 0;
123 }
124
125 /*
126 * Return 0 if the file descriptor is valid, an error otherwise.
127 * If for_select != 0, check whether the file descriptor is within the range
128 * allowed for fd_set used for the FD_xxx macros and the select() function.
129 */
check_fd(int fd,int for_select)130 static int check_fd(int fd, int for_select)
131 {
132 if (fd < 0) {
133 return MBEDTLS_ERR_NET_INVALID_CONTEXT;
134 }
135
136 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
137 !defined(EFI32)
138 (void) for_select;
139 #else
140 /* A limitation of select() is that it only works with file descriptors
141 * that are strictly less than FD_SETSIZE. This is a limitation of the
142 * fd_set type. Error out early, because attempting to call FD_SET on a
143 * large file descriptor is a buffer overflow on typical platforms. */
144 if (for_select && fd >= FD_SETSIZE) {
145 return MBEDTLS_ERR_NET_POLL_FAILED;
146 }
147 #endif
148
149 return 0;
150 }
151
152 /*
153 * Initialize a context
154 */
mbedtls_net_init(mbedtls_net_context * ctx)155 void mbedtls_net_init(mbedtls_net_context *ctx)
156 {
157 ctx->fd = -1;
158 }
159
160 /*
161 * Initiate a TCP connection with host:port and the given protocol
162 */
mbedtls_net_connect(mbedtls_net_context * ctx,const char * host,const char * port,int proto)163 int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host,
164 const char *port, int proto)
165 {
166 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
167 struct addrinfo hints, *addr_list, *cur;
168
169 if ((ret = net_prepare()) != 0) {
170 return ret;
171 }
172
173 /* Do name resolution with both IPv6 and IPv4 */
174 memset(&hints, 0, sizeof(hints));
175 hints.ai_family = AF_UNSPEC;
176 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
177 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
178
179 if (getaddrinfo(host, port, &hints, &addr_list) != 0) {
180 return MBEDTLS_ERR_NET_UNKNOWN_HOST;
181 }
182
183 /* Try the sockaddrs until a connection succeeds */
184 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
185 for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
186 ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
187 cur->ai_protocol);
188 if (ctx->fd < 0) {
189 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
190 continue;
191 }
192
193 if (connect(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) == 0) {
194 ret = 0;
195 break;
196 }
197
198 close(ctx->fd);
199 ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
200 }
201
202 freeaddrinfo(addr_list);
203
204 return ret;
205 }
206
207 /*
208 * Create a listening socket on bind_ip:port
209 */
mbedtls_net_bind(mbedtls_net_context * ctx,const char * bind_ip,const char * port,int proto)210 int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto)
211 {
212 int n, ret;
213 struct addrinfo hints, *addr_list, *cur;
214
215 if ((ret = net_prepare()) != 0) {
216 return ret;
217 }
218
219 /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
220 memset(&hints, 0, sizeof(hints));
221 hints.ai_family = AF_UNSPEC;
222 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
223 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
224 if (bind_ip == NULL) {
225 hints.ai_flags = AI_PASSIVE;
226 }
227
228 if (getaddrinfo(bind_ip, port, &hints, &addr_list) != 0) {
229 return MBEDTLS_ERR_NET_UNKNOWN_HOST;
230 }
231
232 /* Try the sockaddrs until a binding succeeds */
233 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
234 for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
235 ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
236 cur->ai_protocol);
237 if (ctx->fd < 0) {
238 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
239 continue;
240 }
241
242 n = 1;
243 if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR,
244 (const char *) &n, sizeof(n)) != 0) {
245 close(ctx->fd);
246 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
247 continue;
248 }
249
250 if (bind(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) != 0) {
251 close(ctx->fd);
252 ret = MBEDTLS_ERR_NET_BIND_FAILED;
253 continue;
254 }
255
256 /* Listen only makes sense for TCP */
257 if (proto == MBEDTLS_NET_PROTO_TCP) {
258 if (listen(ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG) != 0) {
259 close(ctx->fd);
260 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
261 continue;
262 }
263 }
264
265 /* Bind was successful */
266 ret = 0;
267 break;
268 }
269
270 freeaddrinfo(addr_list);
271
272 return ret;
273
274 }
275
276 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
277 !defined(EFI32)
278 /*
279 * Check if the requested operation would be blocking on a non-blocking socket
280 * and thus 'failed' with a negative return value.
281 */
net_would_block(const mbedtls_net_context * ctx)282 static int net_would_block(const mbedtls_net_context *ctx)
283 {
284 ((void) ctx);
285 return WSAGetLastError() == WSAEWOULDBLOCK;
286 }
287 #else
288 /*
289 * Check if the requested operation would be blocking on a non-blocking socket
290 * and thus 'failed' with a negative return value.
291 *
292 * Note: on a blocking socket this function always returns 0!
293 */
net_would_block(const mbedtls_net_context * ctx)294 static int net_would_block(const mbedtls_net_context *ctx)
295 {
296 int err = errno;
297
298 /*
299 * Never return 'WOULD BLOCK' on a blocking socket
300 */
301 if ((fcntl(ctx->fd, F_GETFL) & O_NONBLOCK) != O_NONBLOCK) {
302 errno = err;
303 return 0;
304 }
305
306 switch (errno = err) {
307 #if defined EAGAIN
308 case EAGAIN:
309 #endif
310 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
311 case EWOULDBLOCK:
312 #endif
313 return 1;
314 }
315 return 0;
316 }
317 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
318
319 /*
320 * Accept a connection from a remote client
321 */
mbedtls_net_accept(mbedtls_net_context * bind_ctx,mbedtls_net_context * client_ctx,void * client_ip,size_t buf_size,size_t * ip_len)322 int mbedtls_net_accept(mbedtls_net_context *bind_ctx,
323 mbedtls_net_context *client_ctx,
324 void *client_ip, size_t buf_size, size_t *ip_len)
325 {
326 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
327 int type;
328
329 struct sockaddr_storage client_addr;
330
331 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
332 defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \
333 defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L)
334 socklen_t n = (socklen_t) sizeof(client_addr);
335 socklen_t type_len = (socklen_t) sizeof(type);
336 #else
337 int n = (int) sizeof(client_addr);
338 int type_len = (int) sizeof(type);
339 #endif
340
341 /* Is this a TCP or UDP socket? */
342 if (getsockopt(bind_ctx->fd, SOL_SOCKET, SO_TYPE,
343 (void *) &type, &type_len) != 0 ||
344 (type != SOCK_STREAM && type != SOCK_DGRAM)) {
345 return MBEDTLS_ERR_NET_ACCEPT_FAILED;
346 }
347
348 if (type == SOCK_STREAM) {
349 /* TCP: actual accept() */
350 ret = client_ctx->fd = (int) accept(bind_ctx->fd,
351 (struct sockaddr *) &client_addr, &n);
352 } else {
353 /* UDP: wait for a message, but keep it in the queue */
354 char buf[1] = { 0 };
355
356 ret = (int) recvfrom(bind_ctx->fd, buf, sizeof(buf), MSG_PEEK,
357 (struct sockaddr *) &client_addr, &n);
358
359 #if defined(_WIN32)
360 if (ret == SOCKET_ERROR &&
361 WSAGetLastError() == WSAEMSGSIZE) {
362 /* We know buf is too small, thanks, just peeking here */
363 ret = 0;
364 }
365 #endif
366 }
367
368 if (ret < 0) {
369 if (net_would_block(bind_ctx) != 0) {
370 return MBEDTLS_ERR_SSL_WANT_READ;
371 }
372
373 return MBEDTLS_ERR_NET_ACCEPT_FAILED;
374 }
375
376 /* UDP: hijack the listening socket to communicate with the client,
377 * then bind a new socket to accept new connections */
378 if (type != SOCK_STREAM) {
379 struct sockaddr_storage local_addr;
380 int one = 1;
381
382 if (connect(bind_ctx->fd, (struct sockaddr *) &client_addr, n) != 0) {
383 return MBEDTLS_ERR_NET_ACCEPT_FAILED;
384 }
385
386 client_ctx->fd = bind_ctx->fd;
387 bind_ctx->fd = -1; /* In case we exit early */
388
389 n = sizeof(struct sockaddr_storage);
390 if (getsockname(client_ctx->fd,
391 (struct sockaddr *) &local_addr, &n) != 0 ||
392 (bind_ctx->fd = (int) socket(local_addr.ss_family,
393 SOCK_DGRAM, IPPROTO_UDP)) < 0 ||
394 setsockopt(bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
395 (const char *) &one, sizeof(one)) != 0) {
396 return MBEDTLS_ERR_NET_SOCKET_FAILED;
397 }
398
399 if (bind(bind_ctx->fd, (struct sockaddr *) &local_addr, n) != 0) {
400 return MBEDTLS_ERR_NET_BIND_FAILED;
401 }
402 }
403
404 if (client_ip != NULL) {
405 if (client_addr.ss_family == AF_INET) {
406 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
407 *ip_len = sizeof(addr4->sin_addr.s_addr);
408
409 if (buf_size < *ip_len) {
410 return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
411 }
412
413 memcpy(client_ip, &addr4->sin_addr.s_addr, *ip_len);
414 } else {
415 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
416 *ip_len = sizeof(addr6->sin6_addr.s6_addr);
417
418 if (buf_size < *ip_len) {
419 return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
420 }
421
422 memcpy(client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
423 }
424 }
425
426 return 0;
427 }
428
429 /*
430 * Set the socket blocking or non-blocking
431 */
mbedtls_net_set_block(mbedtls_net_context * ctx)432 int mbedtls_net_set_block(mbedtls_net_context *ctx)
433 {
434 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
435 !defined(EFI32)
436 u_long n = 0;
437 return ioctlsocket(ctx->fd, FIONBIO, &n);
438 #else
439 return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) & ~O_NONBLOCK);
440 #endif
441 }
442
mbedtls_net_set_nonblock(mbedtls_net_context * ctx)443 int mbedtls_net_set_nonblock(mbedtls_net_context *ctx)
444 {
445 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
446 !defined(EFI32)
447 u_long n = 1;
448 return ioctlsocket(ctx->fd, FIONBIO, &n);
449 #else
450 return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) | O_NONBLOCK);
451 #endif
452 }
453
454 /*
455 * Check if data is available on the socket
456 */
457
mbedtls_net_poll(mbedtls_net_context * ctx,uint32_t rw,uint32_t timeout)458 int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout)
459 {
460 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
461 struct timeval tv;
462
463 fd_set read_fds;
464 fd_set write_fds;
465
466 int fd = ctx->fd;
467
468 ret = check_fd(fd, 1);
469 if (ret != 0) {
470 return ret;
471 }
472
473 #if defined(__has_feature)
474 #if __has_feature(memory_sanitizer)
475 /* Ensure that memory sanitizers consider read_fds and write_fds as
476 * initialized even on platforms such as Glibc/x86_64 where FD_ZERO
477 * is implemented in assembly. */
478 memset(&read_fds, 0, sizeof(read_fds));
479 memset(&write_fds, 0, sizeof(write_fds));
480 #endif
481 #endif
482
483 FD_ZERO(&read_fds);
484 if (rw & MBEDTLS_NET_POLL_READ) {
485 rw &= ~MBEDTLS_NET_POLL_READ;
486 FD_SET((SOCKET) fd, &read_fds);
487 }
488
489 FD_ZERO(&write_fds);
490 if (rw & MBEDTLS_NET_POLL_WRITE) {
491 rw &= ~MBEDTLS_NET_POLL_WRITE;
492 FD_SET((SOCKET) fd, &write_fds);
493 }
494
495 if (rw != 0) {
496 return MBEDTLS_ERR_NET_BAD_INPUT_DATA;
497 }
498
499 tv.tv_sec = timeout / 1000;
500 tv.tv_usec = (timeout % 1000) * 1000;
501
502 do {
503 ret = select(fd + 1, &read_fds, &write_fds, NULL,
504 timeout == (uint32_t) -1 ? NULL : &tv);
505 } while (IS_EINTR(ret));
506
507 if (ret < 0) {
508 return MBEDTLS_ERR_NET_POLL_FAILED;
509 }
510
511 ret = 0;
512 if (FD_ISSET(fd, &read_fds)) {
513 ret |= MBEDTLS_NET_POLL_READ;
514 }
515 if (FD_ISSET(fd, &write_fds)) {
516 ret |= MBEDTLS_NET_POLL_WRITE;
517 }
518
519 return ret;
520 }
521
522 /*
523 * Portable usleep helper
524 */
mbedtls_net_usleep(unsigned long usec)525 void mbedtls_net_usleep(unsigned long usec)
526 {
527 #if defined(_WIN32)
528 Sleep((usec + 999) / 1000);
529 #else
530 struct timeval tv;
531 tv.tv_sec = usec / 1000000;
532 #if defined(__unix__) || defined(__unix) || \
533 (defined(__APPLE__) && defined(__MACH__))
534 tv.tv_usec = (suseconds_t) usec % 1000000;
535 #else
536 tv.tv_usec = usec % 1000000;
537 #endif
538 select(0, NULL, NULL, NULL, &tv);
539 #endif
540 }
541
542 /*
543 * Read at most 'len' characters
544 */
mbedtls_net_recv(void * ctx,unsigned char * buf,size_t len)545 int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
546 {
547 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
548 int fd = ((mbedtls_net_context *) ctx)->fd;
549
550 ret = check_fd(fd, 0);
551 if (ret != 0) {
552 return ret;
553 }
554
555 ret = (int) read(fd, buf, len);
556
557 if (ret < 0) {
558 if (net_would_block(ctx) != 0) {
559 return MBEDTLS_ERR_SSL_WANT_READ;
560 }
561
562 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
563 !defined(EFI32)
564 if (WSAGetLastError() == WSAECONNRESET) {
565 return MBEDTLS_ERR_NET_CONN_RESET;
566 }
567 #else
568 if (errno == EPIPE || errno == ECONNRESET) {
569 return MBEDTLS_ERR_NET_CONN_RESET;
570 }
571
572 if (errno == EINTR) {
573 return MBEDTLS_ERR_SSL_WANT_READ;
574 }
575 #endif
576
577 return MBEDTLS_ERR_NET_RECV_FAILED;
578 }
579
580 return ret;
581 }
582
583 /*
584 * Read at most 'len' characters, blocking for at most 'timeout' ms
585 */
mbedtls_net_recv_timeout(void * ctx,unsigned char * buf,size_t len,uint32_t timeout)586 int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf,
587 size_t len, uint32_t timeout)
588 {
589 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
590 struct timeval tv;
591 fd_set read_fds;
592 int fd = ((mbedtls_net_context *) ctx)->fd;
593
594 ret = check_fd(fd, 1);
595 if (ret != 0) {
596 return ret;
597 }
598
599 FD_ZERO(&read_fds);
600 FD_SET((SOCKET) fd, &read_fds);
601
602 tv.tv_sec = timeout / 1000;
603 tv.tv_usec = (timeout % 1000) * 1000;
604
605 ret = select(fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);
606
607 /* Zero fds ready means we timed out */
608 if (ret == 0) {
609 return MBEDTLS_ERR_SSL_TIMEOUT;
610 }
611
612 if (ret < 0) {
613 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
614 !defined(EFI32)
615 if (WSAGetLastError() == WSAEINTR) {
616 return MBEDTLS_ERR_SSL_WANT_READ;
617 }
618 #else
619 if (errno == EINTR) {
620 return MBEDTLS_ERR_SSL_WANT_READ;
621 }
622 #endif
623
624 return MBEDTLS_ERR_NET_RECV_FAILED;
625 }
626
627 /* This call will not block */
628 return mbedtls_net_recv(ctx, buf, len);
629 }
630
631 /*
632 * Write at most 'len' characters
633 */
mbedtls_net_send(void * ctx,const unsigned char * buf,size_t len)634 int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len)
635 {
636 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
637 int fd = ((mbedtls_net_context *) ctx)->fd;
638
639 ret = check_fd(fd, 0);
640 if (ret != 0) {
641 return ret;
642 }
643
644 ret = (int) write(fd, buf, len);
645
646 if (ret < 0) {
647 if (net_would_block(ctx) != 0) {
648 return MBEDTLS_ERR_SSL_WANT_WRITE;
649 }
650
651 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
652 !defined(EFI32)
653 if (WSAGetLastError() == WSAECONNRESET) {
654 return MBEDTLS_ERR_NET_CONN_RESET;
655 }
656 #else
657 if (errno == EPIPE || errno == ECONNRESET) {
658 return MBEDTLS_ERR_NET_CONN_RESET;
659 }
660
661 if (errno == EINTR) {
662 return MBEDTLS_ERR_SSL_WANT_WRITE;
663 }
664 #endif
665
666 return MBEDTLS_ERR_NET_SEND_FAILED;
667 }
668
669 return ret;
670 }
671
672 /*
673 * Close the connection
674 */
mbedtls_net_close(mbedtls_net_context * ctx)675 void mbedtls_net_close(mbedtls_net_context *ctx)
676 {
677 if (ctx->fd == -1) {
678 return;
679 }
680
681 close(ctx->fd);
682
683 ctx->fd = -1;
684 }
685
686 /*
687 * Gracefully close the connection
688 */
mbedtls_net_free(mbedtls_net_context * ctx)689 void mbedtls_net_free(mbedtls_net_context *ctx)
690 {
691 if (ctx->fd == -1) {
692 return;
693 }
694
695 shutdown(ctx->fd, 2);
696 close(ctx->fd);
697
698 ctx->fd = -1;
699 }
700
701 #endif /* MBEDTLS_NET_C */
702