ssl_tls: fix format warning in ssl_parse_certificate() on x86_64
[tropicssl.git] / library / net.c
blob671af627b0f3f888647272a1763df847ac9acd49
1 /*
2 * TCP networking functions
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "tropicssl/config.h"
38 #if defined(TROPICSSL_NET_C)
40 #include "tropicssl/net.h"
42 #if defined(WIN32) || defined(_WIN32_WCE)
44 #include <winsock2.h>
45 #include <windows.h>
47 #if defined(_WIN32_WCE)
48 #pragma comment( lib, "ws2.lib" )
49 #else
50 #pragma comment( lib, "ws2_32.lib" )
51 #endif
53 #define read(fd,buf,len) recv(fd,buf,len,0)
54 #define write(fd,buf,len) send(fd,buf,len,0)
55 #define close(fd) closesocket(fd)
57 static int wsa_init_done = 0;
59 #else
61 #include <sys/types.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <sys/time.h>
66 #include <unistd.h>
67 #include <signal.h>
68 #include <fcntl.h>
69 #include <netdb.h>
70 #include <errno.h>
72 #endif
74 #include <string.h>
75 #include <stdlib.h>
76 #include <stdio.h>
77 #include <time.h>
80 * htons() is not always available
82 #if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN
83 #define HTONS(n) (n)
84 #else
85 #define HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
86 #endif
87 #define net_htons(n) HTONS(n)
89 * Initiate a TCP connection with host:port
91 int net_connect(int *fd, const char *host, int port)
93 struct sockaddr_in server_addr;
94 struct hostent *server_host;
96 #if defined(WIN32) || defined(_WIN32_WCE)
97 WSADATA wsaData;
99 *fd = -1;
100 if (wsa_init_done == 0) {
101 if (WSAStartup(MAKEWORD(2, 0), &wsaData) == SOCKET_ERROR)
102 return (TROPICSSL_ERR_NET_SOCKET_FAILED);
104 wsa_init_done = 1;
106 #else
107 *fd = -1;
108 signal(SIGPIPE, SIG_IGN);
109 #endif
111 if ((server_host = gethostbyname(host)) == NULL)
112 return (TROPICSSL_ERR_NET_UNKNOWN_HOST);
114 if ((*fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
115 return (TROPICSSL_ERR_NET_SOCKET_FAILED);
117 memcpy((void *)&server_addr.sin_addr,
118 (void *)server_host->h_addr, server_host->h_length);
120 server_addr.sin_family = AF_INET;
121 server_addr.sin_port = net_htons(port);
123 if (connect(*fd, (struct sockaddr *)&server_addr,
124 sizeof(server_addr)) < 0) {
125 close(*fd);
126 *fd = -1;
127 return (TROPICSSL_ERR_NET_CONNECT_FAILED);
130 return (0);
134 * Create a listening socket on bind_ip:port
136 int net_bind(int *fd, const char *bind_ip, int port)
138 int n, c[4];
139 struct sockaddr_in server_addr;
141 #if defined(WIN32) || defined(_WIN32_WCE)
142 WSADATA wsaData;
144 *fd = -1;
145 if (wsa_init_done == 0) {
146 if (WSAStartup(MAKEWORD(2, 0), &wsaData) == SOCKET_ERROR)
147 return (TROPICSSL_ERR_NET_SOCKET_FAILED);
149 wsa_init_done = 1;
151 #else
152 *fd = -1;
153 signal(SIGPIPE, SIG_IGN);
154 #endif
156 if ((*fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
157 return (TROPICSSL_ERR_NET_SOCKET_FAILED);
159 n = 1;
160 setsockopt(*fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&n, sizeof(n));
162 server_addr.sin_addr.s_addr = INADDR_ANY;
163 server_addr.sin_family = AF_INET;
164 server_addr.sin_port = net_htons(port);
166 if (bind_ip != NULL) {
167 memset(c, 0, sizeof(c));
168 sscanf(bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3]);
170 for (n = 0; n < 4; n++)
171 if (c[n] < 0 || c[n] > 255)
172 break;
174 if (n == 4)
175 server_addr.sin_addr.s_addr =
176 ((unsigned long)c[0] << 24) |
177 ((unsigned long)c[1] << 16) |
178 ((unsigned long)c[2] << 8) | ((unsigned long)c[3]);
181 if (bind(*fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
182 close(*fd);
183 *fd = -1;
184 return (TROPICSSL_ERR_NET_BIND_FAILED);
187 if (listen(*fd, 10) != 0) {
188 close(*fd);
189 *fd = -1;
190 return (TROPICSSL_ERR_NET_LISTEN_FAILED);
193 return (0);
197 * Check if the current operation is blocking
199 static int net_is_blocking(void)
201 #if defined(WIN32) || defined(_WIN32_WCE)
202 return (WSAGetLastError() == WSAEWOULDBLOCK);
203 #else
204 switch (errno) {
205 #if defined EAGAIN
206 case EAGAIN:
207 #endif
208 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
209 case EWOULDBLOCK:
210 #endif
211 return (1);
213 return (0);
214 #endif
218 * Accept a connection from a remote client
220 int net_accept(int bind_fd, int *client_fd, void *client_ip)
222 struct sockaddr_in client_addr;
224 #if defined(__socklen_t_defined)
225 socklen_t n = (socklen_t) sizeof(client_addr);
226 #else
227 int n = (int)sizeof(client_addr);
228 #endif
230 *client_fd = accept(bind_fd, (struct sockaddr *)
231 &client_addr, &n);
233 if (*client_fd < 0) {
234 if (net_is_blocking() != 0)
235 return (TROPICSSL_ERR_NET_TRY_AGAIN);
237 return (TROPICSSL_ERR_NET_ACCEPT_FAILED);
240 if (client_ip != NULL)
241 memcpy(client_ip, &client_addr.sin_addr.s_addr,
242 sizeof(client_addr.sin_addr.s_addr));
244 return (0);
248 * Set the socket blocking or non-blocking
250 int net_set_block(int fd)
252 #if defined(WIN32) || defined(_WIN32_WCE)
253 long n = 0;
254 return (ioctlsocket(fd, FIONBIO, &n));
255 #else
256 return (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK));
257 #endif
260 int net_set_nonblock(int fd)
262 #if defined(WIN32) || defined(_WIN32_WCE)
263 long n = 1;
264 return (ioctlsocket(fd, FIONBIO, &n));
265 #else
266 return (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK));
267 #endif
271 * Portable usleep helper
273 void net_usleep(unsigned long usec)
275 struct timeval tv;
276 tv.tv_sec = 0;
277 tv.tv_usec = usec;
278 select(0, NULL, NULL, NULL, &tv);
282 * Read at most 'len' characters
284 int net_recv(void *ctx, unsigned char *buf, int len)
286 int ret = read(*((int *)ctx), buf, len);
288 if (len > 0 && ret == 0)
289 return (TROPICSSL_ERR_NET_CONN_RESET);
291 if (ret < 0) {
292 if (net_is_blocking() != 0)
293 return (TROPICSSL_ERR_NET_TRY_AGAIN);
295 #if defined(WIN32) || defined(_WIN32_WCE)
296 if (WSAGetLastError() == WSAECONNRESET)
297 return (TROPICSSL_ERR_NET_CONN_RESET);
298 #else
299 if (errno == EPIPE || errno == ECONNRESET)
300 return (TROPICSSL_ERR_NET_CONN_RESET);
302 if (errno == EINTR)
303 return (TROPICSSL_ERR_NET_TRY_AGAIN);
304 #endif
306 return (TROPICSSL_ERR_NET_RECV_FAILED);
309 return (ret);
313 * Write at most 'len' characters
315 int net_send(void *ctx, const unsigned char *buf, int len)
317 int ret = write(*((int *)ctx), buf, len);
319 if (ret < 0) {
320 if (net_is_blocking() != 0)
321 return (TROPICSSL_ERR_NET_TRY_AGAIN);
323 #if defined(WIN32) || defined(_WIN32_WCE)
324 if (WSAGetLastError() == WSAECONNRESET)
325 return (TROPICSSL_ERR_NET_CONN_RESET);
326 #else
327 if (errno == EPIPE || errno == ECONNRESET)
328 return (TROPICSSL_ERR_NET_CONN_RESET);
330 if (errno == EINTR)
331 return (TROPICSSL_ERR_NET_TRY_AGAIN);
332 #endif
334 return (TROPICSSL_ERR_NET_SEND_FAILED);
337 return (ret);
341 * Gracefully close the connection
343 void net_close(int fd)
345 if (fd >= 0) {
346 shutdown(fd, 2);
347 close(fd);
351 #endif