blob: 4334ce97dacaf07cd301f8384bb3e27a8dde946d [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/* Copyright (C) 2007-2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +020012#ifdef __linux__ /* Recent versions of glibc only define EAI_NODATA, which is an
13 extension to the POSIX standard, if _GNU_SOURCE is defined. */
14# define _GNU_SOURCE 1
15#endif
16
David 'Digit' Turnercc330d42013-12-14 23:26:42 +010017#include "android/sockets.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080018#include <fcntl.h>
19#include <stddef.h>
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010020#include "android/qemu-debug.h"
David 'Digit' Turnere7216d82013-12-15 00:51:13 +010021#include "sysemu/char.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080022#include <stdlib.h>
23#include <string.h>
24#include "android/utils/path.h"
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +020025#include "android/utils/debug.h"
David 'Digit' Turneraf81d742014-02-03 17:11:18 +010026#include "android/utils/eintr_wrapper.h"
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070027#include "android/utils/misc.h"
David 'Digit' Turner18fe86e2010-10-19 08:07:11 +020028#include "android/utils/system.h"
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +020029
30#define D(...) VERBOSE_PRINT(socket,__VA_ARGS__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080031
32#ifdef _WIN32
33# define xxWIN32_LEAN_AND_MEAN
34# include <windows.h>
35# include <winsock2.h>
36# include <ws2tcpip.h>
37#else /* !_WIN32 */
38# include <sys/ioctl.h>
39# include <sys/socket.h>
40# include <netinet/in.h>
41# include <netinet/tcp.h>
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +020042# include <netdb.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080043# if HAVE_UNIX_SOCKETS
44# include <sys/un.h>
45# ifndef UNIX_PATH_MAX
46# define UNIX_PATH_MAX (sizeof(((struct sockaddr_un*)0)->sun_path)-1)
47# endif
48# endif
49#endif /* !_WIN32 */
50
51
52
53/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
54 * easily in QEMU since we use SIGALRM to implement periodic timers
55 */
56#ifdef _WIN32
57# define QSOCKET_CALL(_ret,_cmd) \
58 do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
59#else
60# define QSOCKET_CALL(_ret,_cmd) \
David 'Digit' Turner7410e8a2009-05-20 10:57:56 +020061 do { \
62 errno = 0; \
David 'Digit' Turneraf81d742014-02-03 17:11:18 +010063 _ret = HANDLE_EINTR(_cmd); \
David 'Digit' Turner7410e8a2009-05-20 10:57:56 +020064 } while (0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080065#endif
66
67#ifdef _WIN32
68
69#include <errno.h>
70
71static int winsock_error;
72
73#define WINSOCK_ERRORS_LIST \
74 EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
75 EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
76 EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
77 EE(WSAEINTR,EINTR,"interrupted function call") \
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070078 EE(WSAEALREADY,EALREADY,"operation already in progress") \
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080079 EE(WSAEBADF,EBADF,"bad file descriptor") \
80 EE(WSAEACCES,EACCES,"permission denied") \
81 EE(WSAEFAULT,EFAULT,"bad address") \
82 EE(WSAEINVAL,EINVAL,"invalid argument") \
83 EE(WSAEMFILE,EMFILE,"too many opened files") \
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070084 EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \
85 EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080086 EE(WSAEALREADY,EAGAIN,"operation already in progress") \
87 EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
88 EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
89 EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
90 EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
91 EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
92 EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
93 EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
94 EE(WSAENETDOWN,ENETDOWN,"network is down") \
95 EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
96 EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
97 EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
98 EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
99 EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
100 EE(WSAEISCONN,EISCONN,"socket is already connected") \
101 EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
102 EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
103 EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
104 EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
105 EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
106 EE(WSAELOOP,ELOOP,"cannot translate name") \
107 EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
108 EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
109 EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
110
111typedef struct {
112 int winsock;
113 int unix;
114 const char* string;
115} WinsockError;
116
117static const WinsockError _winsock_errors[] = {
118#define EE(w,u,s) { w, u, s },
119 WINSOCK_ERRORS_LIST
120#undef EE
121 { -1, -1, NULL }
122};
123
124/* this function reads the latest winsock error code and updates
125 * errno to a matching value. It also returns the new value of
126 * errno.
127 */
128static int
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800129fix_errno( void )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800130{
131 const WinsockError* werr = _winsock_errors;
132 int unix = EINVAL; /* generic error code */
133
David 'Digit' Turner26722dd2011-02-24 16:40:20 +0100134 winsock_error = WSAGetLastError();
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200135
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800136 for ( ; werr->string != NULL; werr++ ) {
137 if (werr->winsock == winsock_error) {
138 unix = werr->unix;
139 break;
140 }
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +0200141 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800142 errno = unix;
143 return -1;
144}
145
146static int
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800147set_errno( int code )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800148{
149 winsock_error = -1;
150 errno = code;
151 return -1;
152}
153
154/* this function returns a string describing the latest Winsock error */
155const char*
156_errno_str(void)
157{
158 const WinsockError* werr = _winsock_errors;
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -0700159 const char* result = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800160
161 for ( ; werr->string; werr++ ) {
162 if (werr->winsock == winsock_error) {
163 result = werr->string;
164 break;
165 }
166 }
167
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -0700168 if (result == NULL) {
169 result = tempstr_format(
170 "Unkown socket error (Winsock=0x%08x) errno=%d: %s",
171 winsock_error, errno, strerror(errno));
172 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800173 return result;
174}
175#else
176static int
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800177fix_errno( void )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800178{
179 return -1;
180}
181
182static int
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800183set_errno( int code )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800184{
185 errno = code;
186 return -1;
187}
188#endif
189
190/* socket types */
191
192static int
193socket_family_to_bsd( SocketFamily family )
194{
195 switch (family) {
196 case SOCKET_INET: return AF_INET;
197 case SOCKET_IN6: return AF_INET6;
198#if HAVE_UNIX_SOCKETS
199 case SOCKET_UNIX: return AF_LOCAL;
200#endif
201 default: return -1;
202 }
203}
204
205static int
206socket_type_to_bsd( SocketType type )
207{
208 switch (type) {
209 case SOCKET_DGRAM: return SOCK_DGRAM;
210 case SOCKET_STREAM: return SOCK_STREAM;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700211 default: return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800212 }
213}
214
215static SocketType
216socket_type_from_bsd( int type )
217{
218 switch (type) {
219 case SOCK_DGRAM: return SOCKET_DGRAM;
220 case SOCK_STREAM: return SOCKET_STREAM;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700221 default: return (SocketType) SOCKET_UNSPEC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800222 }
223}
224
225#if 0
226static int
227socket_type_check( SocketType type )
228{
229 return (type == SOCKET_DGRAM || type == SOCKET_STREAM);
230}
231#endif
232
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700233typedef union {
234 struct sockaddr sa[1];
235 struct sockaddr_in in[1];
236#if HAVE_IN6_SOCKETS
237 struct sockaddr_in6 in6[1];
238#endif
239#if HAVE_UNIX_SOCKETS
240 struct sockaddr_un un[1];
241#endif
242} sockaddr_storage;
243
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244/* socket addresses */
245
246void
247sock_address_init_inet( SockAddress* a, uint32_t ip, uint16_t port )
248{
249 a->family = SOCKET_INET;
250 a->u.inet.port = port;
251 a->u.inet.address = ip;
252}
253
254void
255sock_address_init_in6 ( SockAddress* a, const uint8_t* ip6[16], uint16_t port )
256{
257 a->family = SOCKET_IN6;
258 a->u.in6.port = port;
259 memcpy( a->u.in6.address, ip6, sizeof(a->u.in6.address) );
260}
261
262void
263sock_address_init_unix( SockAddress* a, const char* path )
264{
265 a->family = SOCKET_UNIX;
266 a->u._unix.path = strdup(path ? path : "");
267 a->u._unix.owner = 1;
268}
269
270void sock_address_done( SockAddress* a )
271{
272 if (a->family == SOCKET_UNIX && a->u._unix.owner) {
273 a->u._unix.owner = 0;
274 free((char*)a->u._unix.path);
275 }
276}
277
278static char*
279format_char( char* buf, char* end, int c )
280{
David 'Digit' Turner0b7cd6c2009-07-10 00:54:05 +0200281 if (buf < end) {
282 if (buf+1 == end) {
283 *buf++ = 0;
284 } else {
285 *buf++ = (char) c;
286 *buf = 0;
287 }
288 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800289 return buf;
290}
291
292static char*
293format_str( char* buf, char* end, const char* str )
294{
295 int len = strlen(str);
296 int avail = end - buf;
297
298 if (len > avail)
299 len = avail;
300
301 memcpy( buf, str, len );
302 buf += len;
303
304 if (buf == end)
305 buf[-1] = 0;
306 else
307 buf[0] = 0;
308
309 return buf;
310}
311
312static char*
313format_unsigned( char* buf, char* end, unsigned val )
314{
315 char temp[16];
316 int nn;
317
318 for ( nn = 0; val != 0; nn++ ) {
319 int rem = val % 10;
320 temp[nn] = '0'+rem;
321 val /= 10;
322 }
323
324 if (nn == 0)
325 temp[nn++] = '0';
326
327 while (nn > 0)
328 buf = format_char(buf, end, temp[--nn]);
329
330 return buf;
331}
332
333static char*
334format_hex( char* buf, char* end, unsigned val, int ndigits )
335{
336 int shift = 4*ndigits;
337 static const char hex[16] = "0123456789abcdef";
338
339 while (shift >= 0) {
340 buf = format_char(buf, end, hex[(val >> shift) & 15]);
341 shift -= 4;
342 }
343 return buf;
344}
345
346static char*
347format_ip4( char* buf, char* end, uint32_t ip )
348{
349 buf = format_unsigned( buf, end, (unsigned)(ip >> 24) );
350 buf = format_char( buf, end, '.');
351 buf = format_unsigned( buf, end, (unsigned)((ip >> 16) & 255));
352 buf = format_char( buf, end, '.');
353 buf = format_unsigned( buf, end, (unsigned)((ip >> 8) & 255));
354 buf = format_char( buf, end, '.');
355 buf = format_unsigned( buf, end, (unsigned)(ip & 255));
356 return buf;
357}
358
359static char*
360format_ip6( char* buf, char* end, const uint8_t* ip6 )
361{
362 int nn;
363 for (nn = 0; nn < 8; nn++) {
364 int val = (ip6[0] << 16) | ip6[1];
365 ip6 += 2;
366 if (nn > 0)
367 buf = format_char(buf, end, ':');
368 if (val == 0)
369 continue;
370 buf = format_hex(buf, end, val, 4);
371 }
372 return buf;
373}
374
375const char*
376sock_address_to_string( const SockAddress* a )
377{
378 static char buf0[MAX_PATH];
David 'Digit' Turner0b7cd6c2009-07-10 00:54:05 +0200379 char *buf = buf0, *end = buf + sizeof(buf0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800380
381 switch (a->family) {
382 case SOCKET_INET:
383 buf = format_ip4( buf, end, a->u.inet.address );
384 buf = format_char( buf, end, ':' );
385 buf = format_unsigned( buf, end, (unsigned) a->u.inet.port );
386 break;
387
388 case SOCKET_IN6:
389 buf = format_ip6( buf, end, a->u.in6.address );
390 buf = format_char( buf, end, ':' );
391 buf = format_unsigned( buf, end, (unsigned) a->u.in6.port );
392 break;
393
394 case SOCKET_UNIX:
395 buf = format_str( buf, end, a->u._unix.path );
396 break;
397
398 default:
399 return NULL;
400 }
401
402 return buf0;
403}
404
405int
406sock_address_equal( const SockAddress* a, const SockAddress* b )
407{
408 if (a->family != b->family)
409 return 0;
410
411 switch (a->family) {
412 case SOCKET_INET:
413 return (a->u.inet.address == b->u.inet.address &&
414 a->u.inet.port == b->u.inet.port);
415
416 case SOCKET_IN6:
417 return (!memcmp(a->u.in6.address, b->u.in6.address, 16) &&
418 a->u.in6.port == b->u.in6.port);
419
420 case SOCKET_UNIX:
421 return (!strcmp(a->u._unix.path, b->u._unix.path));
422
423 default:
424 return 0;
425 }
426}
427
428int
429sock_address_get_port( const SockAddress* a )
430{
431 switch (a->family) {
432 case SOCKET_INET:
433 return a->u.inet.port;
434 case SOCKET_IN6:
435 return a->u.in6.port;
436 default:
437 return -1;
438 }
439}
440
441void
442sock_address_set_port( SockAddress* a, uint16_t port )
443{
444 switch (a->family) {
445 case SOCKET_INET:
446 a->u.inet.port = port;
447 break;
448 case SOCKET_IN6:
449 a->u.in6.port = port;
450 break;
451 default:
452 ;
453 }
454}
455
456const char*
457sock_address_get_path( const SockAddress* a )
458{
459 if (a->family == SOCKET_UNIX)
460 return a->u._unix.path;
461 else
462 return NULL;
463}
464
465int
466sock_address_get_ip( const SockAddress* a )
467{
468 if (a->family == SOCKET_INET)
469 return a->u.inet.address;
470
471 return -1;
472}
473
474#if 0
475char*
476bufprint_sock_address( char* p, char* end, const SockAddress* a )
477{
478 switch (a->family) {
479 case SOCKET_INET:
480 {
481 uint32_t ip = a->u.inet.address;
482
483 return bufprint( p, end, "%d.%d.%d.%d:%d",
484 (ip >> 24) & 255, (ip >> 16) & 255,
485 (ip >> 8) & 255, ip & 255,
486 a->u.inet.port );
487 }
488 case SOCKET_IN6:
489 {
490 int nn = 0;
491 const char* column = "";
492 const uint8_t* tab = a->u.in6.address;
493 for (nn = 0; nn < 16; nn += 2) {
494 p = bufprint(p, end, "%s%04x", column, (tab[n] << 8) | tab[n+1]);
495 column = ":";
496 }
497 return bufprint(p, end, ":%d", a->u.in6.port);
498 }
499 case SOCKET_UNIX:
500 {
501 return bufprint(p, end, "%s", a->u._unix.path);
502 }
503 default:
504 return p;
505 }
506}
507#endif
508
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700509static int
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200510sock_address_to_bsd( const SockAddress* a, sockaddr_storage* paddress, socklen_t *psize )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800511{
512 switch (a->family) {
513 case SOCKET_INET:
514 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700515 struct sockaddr_in* dst = paddress->in;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800516
517 *psize = sizeof(*dst);
518
519 memset( paddress, 0, *psize );
520
521 dst->sin_family = AF_INET;
522 dst->sin_port = htons(a->u.inet.port);
523 dst->sin_addr.s_addr = htonl(a->u.inet.address);
524 }
525 break;
526
527#if HAVE_IN6_SOCKETS
528 case SOCKET_IN6:
529 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700530 struct sockaddr_in6* dst = paddress->in6;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800531
532 *psize = sizeof(*dst);
533
534 memset( paddress, 0, *psize );
535
536 dst->sin6_family = AF_INET6;
537 dst->sin6_port = htons(a->u.in6.port);
538 memcpy( dst->sin6_addr.s6_addr, a->u.in6.address, 16 );
539 }
540 break;
541#endif /* HAVE_IN6_SOCKETS */
542
543#if HAVE_UNIX_SOCKETS
544 case SOCKET_UNIX:
545 {
546 int slen = strlen(a->u._unix.path);
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700547 struct sockaddr_un* dst = paddress->un;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800548
549 if (slen >= UNIX_PATH_MAX)
550 return -1;
551
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700552 memset( dst, 0, sizeof(*dst) );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800553
554 dst->sun_family = AF_LOCAL;
555 memcpy( dst->sun_path, a->u._unix.path, slen );
556 dst->sun_path[slen] = 0;
557
558 *psize = (char*)&dst->sun_path[slen+1] - (char*)dst;
559 }
560 break;
561#endif /* HAVE_UNIX_SOCKETS */
562
563 default:
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800564 return set_errno(EINVAL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800565 }
566
567 return 0;
568}
569
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700570static int
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200571sock_address_from_bsd( SockAddress* a, const void* from, size_t fromlen )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800572{
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200573 switch (((struct sockaddr *)from)->sa_family) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800574 case AF_INET:
575 {
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200576 const struct sockaddr_in* src = from;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800577
578 if (fromlen < sizeof(*src))
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800579 return set_errno(EINVAL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800580
581 a->family = SOCKET_INET;
582 a->u.inet.port = ntohs(src->sin_port);
583 a->u.inet.address = ntohl(src->sin_addr.s_addr);
584 }
585 break;
586
587#ifdef HAVE_IN6_SOCKETS
588 case AF_INET6:
589 {
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200590 const struct sockaddr_in6* src = from;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800591
592 if (fromlen < sizeof(*src))
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800593 return set_errno(EINVAL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800594
595 a->family = SOCKET_IN6;
596 a->u.in6.port = ntohs(src->sin6_port);
597 memcpy(a->u.in6.address, src->sin6_addr.s6_addr, 16);
598 }
599 break;
600#endif
601
602#ifdef HAVE_UNIX_SOCKETS
603 case AF_LOCAL:
604 {
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200605 const struct sockaddr_un* src = from;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800606 char* end;
607
608 if (fromlen < sizeof(*src))
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800609 return set_errno(EINVAL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800610
611 /* check that the path is zero-terminated */
612 end = memchr(src->sun_path, 0, UNIX_PATH_MAX);
613 if (end == NULL)
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800614 return set_errno(EINVAL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800615
616 a->family = SOCKET_UNIX;
617 a->u._unix.owner = 1;
618 a->u._unix.path = strdup(src->sun_path);
619 }
620 break;
621#endif
622
623 default:
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800624 return set_errno(EINVAL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800625 }
626 return 0;
627}
628
629
630int
631sock_address_init_resolve( SockAddress* a, const char* hostname, uint16_t port, int preferIn6 )
632{
633 struct addrinfo hints[1];
634 struct addrinfo* res;
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200635 int ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800636
637 memset(hints, 0, sizeof(hints));
638 hints->ai_family = preferIn6 ? AF_INET6 : AF_UNSPEC;
639
David Turner669c4792009-04-13 17:58:45 -0700640 ret = getaddrinfo(hostname, NULL, hints, &res);
641 if (ret != 0) {
642 int err;
643
644 switch (ret) {
645 case EAI_AGAIN: /* server is down */
646 case EAI_FAIL: /* server is sick */
647 err = EHOSTDOWN;
648 break;
649
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800650/* NOTE that in x86_64-w64-mingw32 both EAI_NODATA and EAI_NONAME are the same */
651#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
David Turner669c4792009-04-13 17:58:45 -0700652 case EAI_NODATA:
Nick Pellyf5be61d2009-04-24 15:28:40 -0700653#endif
David Turner669c4792009-04-13 17:58:45 -0700654 case EAI_NONAME:
655 err = ENOENT;
656 break;
657
658 case EAI_MEMORY:
659 err = ENOMEM;
660 break;
661
662 default:
663 err = EINVAL;
664 }
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800665 return set_errno(err);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800666 }
667
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +0200668 /* Parse the returned list of addresses. */
669 {
670 struct addrinfo* res_ipv4 = NULL;
671 struct addrinfo* res_ipv6 = NULL;
672 struct addrinfo* r;
673
674 /* If preferIn6 is false, we stop on the first IPv4 address,
675 * otherwise, we stop on the first IPv6 one
676 */
677 for (r = res; r != NULL; r = r->ai_next) {
678 if (r->ai_family == AF_INET && res_ipv4 == NULL) {
679 res_ipv4 = r;
680 if (!preferIn6)
681 break;
682 }
683 else if (r->ai_family == AF_INET6 && res_ipv6 == NULL) {
684 res_ipv6 = r;
685 if (preferIn6)
686 break;
687 }
688 }
689
690 /* Select the best address in 'r', which will be NULL
691 * if there is no corresponding address.
692 */
693 if (preferIn6) {
694 r = res_ipv6;
695 if (r == NULL)
696 r = res_ipv4;
697 } else {
698 r = res_ipv4;
699 if (r == NULL)
700 r = res_ipv6;
701 }
702
703 if (r == NULL) {
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800704 ret = set_errno(ENOENT);
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +0200705 goto Exit;
706 }
707
708 /* Convert to a SockAddress */
709 ret = sock_address_from_bsd( a, r->ai_addr, r->ai_addrlen );
710 if (ret < 0)
711 goto Exit;
712 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800713
714 /* need to set the port */
715 switch (a->family) {
716 case SOCKET_INET: a->u.inet.port = port; break;
717 case SOCKET_IN6: a->u.in6.port = port; break;
718 default: ;
719 }
720
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +0200721Exit:
722 freeaddrinfo(res);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800723 return ret;
724}
725
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700726/* The Winsock headers for mingw lack some definitions */
727#ifndef AI_ADDRCONFIG
728# define AI_ADDRCONFIG 0
729#endif
730
731SockAddress**
732sock_address_list_create( const char* hostname,
733 const char* port,
734 unsigned flags )
735{
736 SockAddress** list = NULL;
737 SockAddress* addr;
738 int nn, count, ret;
739 struct addrinfo ai, *res, *e;
740
741 memset(&ai, 0, sizeof(ai));
742 ai.ai_flags |= AI_ADDRCONFIG;
743 ai.ai_family = PF_UNSPEC;
744
745 if (flags & SOCKET_LIST_FORCE_INET)
746 ai.ai_family = PF_INET;
747 else if (flags & SOCKET_LIST_FORCE_IN6)
748 ai.ai_family = PF_INET6;
749
750 if (flags & SOCKET_LIST_PASSIVE)
751 ai.ai_flags |= AI_PASSIVE;
752 else
753 ai.ai_flags |= AI_CANONNAME;
754
David 'Digit' Turnerc611a192010-12-22 22:30:20 +0100755 if (flags & SOCKET_LIST_DGRAM)
756 ai.ai_socktype = SOCK_DGRAM;
757
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700758 while (1) {
759 struct addrinfo hints = ai;
760
761 ret = getaddrinfo(hostname, port, &hints, &res);
762 if (ret == 0)
763 break;
764
765 switch (ret) {
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200766#ifdef EAI_ADDRFAMILY
767 case EAI_ADDRFAMILY:
768#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700769 case EAI_NODATA:
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800770 set_errno(ENOENT);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700771 break;
772 case EAI_FAMILY:
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800773 set_errno(EAFNOSUPPORT);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700774 break;
775 case EAI_AGAIN:
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800776 set_errno(EAGAIN);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700777 break;
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200778#ifdef EAI_SYSTEM
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700779 case EAI_SYSTEM:
780 if (errno == EINTR)
781 continue;
782 break;
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200783#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700784 default:
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800785 set_errno(EINVAL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700786 }
787 return NULL;
788 }
789
790 /* allocate result list */
791 for (count = 0, e = res; e != NULL; e = e->ai_next)
792 count += 1;
793
David 'Digit' Turner18fe86e2010-10-19 08:07:11 +0200794 AARRAY_NEW(list, count+1);
795 AARRAY_NEW(addr, count);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700796
797 for (nn = 0, e = res; e != NULL; e = e->ai_next) {
798
799 ret = sock_address_from_bsd(addr, e->ai_addr, e->ai_addrlen);
800 if (ret < 0)
801 continue;
802
803 list[nn++] = addr++;
804 }
805 list[nn] = NULL;
806 freeaddrinfo(res);
807 return list;
808}
809
Vladimir Chtchetkine50eef012010-11-24 08:30:47 -0800810SockAddress**
811sock_address_list_create2(const char* host_and_port, unsigned flags )
812{
813 char host_name[512];
814 const char* actual_host_name = "localhost";
815 // Parse host and port name.
816 const char* port_name = strchr(host_and_port, ':');
817 if (port_name != NULL) {
818 int to_copy = MIN(sizeof(host_name)-1, port_name - host_and_port);
819 if (to_copy != 0) {
820 memcpy(host_name, host_and_port, to_copy);
821 host_name[to_copy] = '\0';
822 actual_host_name = host_name;
823 port_name++;
824 } else {
825 return NULL;
826 }
827 } else {
828 port_name = host_and_port;
829 }
830 // Make sure that port_name is not empty.
831 if (port_name[0] == '\0') {
832 return NULL;
833 }
834 return sock_address_list_create(actual_host_name, port_name, flags);
835}
836
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700837void
838sock_address_list_free( SockAddress** list )
839{
840 int nn;
841 SockAddress* addr;
842
843 if (list == NULL)
844 return;
845
846 addr = list[0];
847 for (nn = 0; list[nn] != NULL; nn++) {
848 sock_address_done(list[nn]);
849 list[nn] = NULL;
850 }
David 'Digit' Turner18fe86e2010-10-19 08:07:11 +0200851 AFREE(addr);
852 AFREE(list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700853}
854
855int
856sock_address_get_numeric_info( SockAddress* a,
857 char* host,
858 size_t hostlen,
859 char* serv,
860 size_t servlen )
861{
862 struct sockaddr* saddr;
863 socklen_t slen;
864 int ret;
865
866 switch (a->family) {
867 case SOCKET_INET:
868 saddr = (struct sockaddr*) &a->u.inet.address;
869 slen = sizeof(a->u.inet.address);
870 break;
871
872#if HAVE_IN6_SOCKET
873 case SOCKET_IN6:
874 saddr = (struct sockaddr*) &a->u.in6.address;
875 slen = sizeof(a->u.in6.address);
876 break;
877#endif
878 default:
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800879 return set_errno(EINVAL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700880 }
881
882 ret = getnameinfo( saddr, slen, host, hostlen, serv, servlen,
883 NI_NUMERICHOST | NI_NUMERICSERV );
884
885 switch (ret) {
886 case 0:
887 break;
888 case EAI_AGAIN:
889 ret = EAGAIN;
890 break;
891 default:
892 ret = EINVAL;
893 }
894 return ret;
895}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800896
897int
898socket_create( SocketFamily family, SocketType type )
899{
900 int ret;
901 int sfamily = socket_family_to_bsd(family);
902 int stype = socket_type_to_bsd(type);
903
904 if (sfamily < 0 || stype < 0) {
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800905 return set_errno(EINVAL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800906 }
907
908 QSOCKET_CALL(ret, socket(sfamily, stype, 0));
909 if (ret < 0)
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800910 return fix_errno();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800911
912 return ret;
913}
914
915
916int
917socket_create_inet( SocketType type )
918{
919 return socket_create( SOCKET_INET, type );
920}
921
922#if HAVE_IN6_SOCKETS
923int
924socket_create_in6 ( SocketType type )
925{
926 return socket_create( SOCKET_IN6, type );
927}
928#endif
929
930#if HAVE_UNIX_SOCKETS
931int
932socket_create_unix( SocketType type )
933{
934 return socket_create( SOCKET_UNIX, type );
935}
936#endif
937
938int socket_can_read(int fd)
939{
940#ifdef _WIN32
941 unsigned long opt;
942
943 if (ioctlsocket(fd, FIONREAD, &opt) < 0)
944 return 0;
945
946 return opt;
947#else
948 int opt;
949
950 if (ioctl(fd, FIONREAD, &opt) < 0)
951 return 0;
952
953 return opt;
954#endif
955}
956
957#define SOCKET_CALL(cmd) \
958 int ret; \
959 QSOCKET_CALL(ret, (cmd)); \
960 if (ret < 0) \
Andrew Hsieh7f661af2012-05-02 13:24:28 +0800961 return fix_errno(); \
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800962 return ret; \
963
964int
965socket_send(int fd, const void* buf, int buflen)
966{
967 SOCKET_CALL(send(fd, buf, buflen, 0))
968}
969
970int
971socket_send_oob( int fd, const void* buf, int buflen )
972{
973 SOCKET_CALL(send(fd, buf, buflen, MSG_OOB));
974}
975
976int
977socket_sendto(int fd, const void* buf, int buflen, const SockAddress* to)
978{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700979 sockaddr_storage sa;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800980 socklen_t salen;
981
982 if (sock_address_to_bsd(to, &sa, &salen) < 0)
983 return -1;
984
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700985 SOCKET_CALL(sendto(fd, buf, buflen, 0, sa.sa, salen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800986}
987
988int
989socket_recv(int fd, void* buf, int len)
990{
991 SOCKET_CALL(recv(fd, buf, len, 0));
992}
993
994int
995socket_recvfrom(int fd, void* buf, int len, SockAddress* from)
996{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700997 sockaddr_storage sa;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800998 socklen_t salen = sizeof(sa);
999 int ret;
1000
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001001 QSOCKET_CALL(ret,recvfrom(fd,buf,len,0,sa.sa,&salen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001002 if (ret < 0)
Andrew Hsieh7f661af2012-05-02 13:24:28 +08001003 return fix_errno();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001004
1005 if (sock_address_from_bsd(from, &sa, salen) < 0)
1006 return -1;
1007
1008 return ret;
1009}
1010
1011int
1012socket_connect( int fd, const SockAddress* address )
1013{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001014 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001015 socklen_t addrlen;
1016
1017 if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
1018 return -1;
1019
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001020 SOCKET_CALL(connect(fd,addr.sa,addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001021}
1022
1023int
1024socket_bind( int fd, const SockAddress* address )
1025{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001026 sockaddr_storage addr;
1027 socklen_t addrlen;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001028
1029 if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
1030 return -1;
1031
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001032 SOCKET_CALL(bind(fd, addr.sa, addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001033}
1034
1035int
1036socket_get_address( int fd, SockAddress* address )
1037{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001038 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001039 socklen_t addrlen = sizeof(addr);
1040 int ret;
1041
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001042 QSOCKET_CALL(ret, getsockname(fd, addr.sa, &addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001043 if (ret < 0)
Andrew Hsieh7f661af2012-05-02 13:24:28 +08001044 return fix_errno();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001045
1046 return sock_address_from_bsd(address, &addr, addrlen);
1047}
1048
1049int
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001050socket_get_peer_address( int fd, SockAddress* address )
1051{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001052 sockaddr_storage addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001053 socklen_t addrlen = sizeof(addr);
1054 int ret;
1055
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001056 QSOCKET_CALL(ret, getpeername(fd, addr.sa, &addrlen));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001057 if (ret < 0)
Andrew Hsieh7f661af2012-05-02 13:24:28 +08001058 return fix_errno();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001059
1060 return sock_address_from_bsd(address, &addr, addrlen);
1061}
1062
1063int
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001064socket_listen( int fd, int backlog )
1065{
1066 SOCKET_CALL(listen(fd, backlog));
1067}
1068
1069int
1070socket_accept( int fd, SockAddress* address )
1071{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001072 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001073 socklen_t addrlen = sizeof(addr);
1074 int ret;
1075
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001076 QSOCKET_CALL(ret, accept(fd, addr.sa, &addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001077 if (ret < 0)
Andrew Hsieh7f661af2012-05-02 13:24:28 +08001078 return fix_errno();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001079
1080 if (address) {
1081 if (sock_address_from_bsd(address, &addr, addrlen) < 0) {
1082 socket_close(ret);
1083 return -1;
1084 }
1085 }
1086 return ret;
1087}
1088
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001089static int
1090socket_getoption(int fd, int domain, int option, int defaut)
1091{
1092 int ret;
1093 while (1) {
1094#ifdef _WIN32
1095 DWORD opt = (DWORD)-1;
1096#else
1097 int opt = -1;
1098#endif
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001099 socklen_t optlen = sizeof(opt);
David 'Digit' Turneraf81d742014-02-03 17:11:18 +01001100 ret = HANDLE_EINTR(
1101 getsockopt(fd, domain, option, (char*)&opt, &optlen));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001102 if (ret == 0)
1103 return (int)opt;
David 'Digit' Turneraf81d742014-02-03 17:11:18 +01001104 else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001105 return defaut;
1106 }
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001107#undef OPT_CAST
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001108}
1109
1110
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001111SocketType socket_get_type(int fd)
1112{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001113 int so_type = socket_getoption(fd, SOL_SOCKET, SO_TYPE, -1);
1114 return socket_type_from_bsd(so_type);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001115}
1116
1117int socket_set_nonblock(int fd)
1118{
1119#ifdef _WIN32
1120 unsigned long opt = 1;
1121 return ioctlsocket(fd, FIONBIO, &opt);
1122#else
1123 int flags = fcntl(fd, F_GETFL);
1124 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
1125#endif
1126}
1127
1128int socket_set_blocking(int fd)
1129{
1130#ifdef _WIN32
1131 unsigned long opt = 0;
1132 return ioctlsocket(fd, FIONBIO, &opt);
1133#else
1134 int flags = fcntl(fd, F_GETFL);
1135 return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
1136#endif
1137}
1138
1139static int
1140socket_setoption(int fd, int domain, int option, int _flag)
1141{
1142#ifdef _WIN32
1143 DWORD flag = (DWORD) _flag;
1144#else
1145 int flag = _flag;
1146#endif
1147 return setsockopt( fd, domain, option, (const char*)&flag, sizeof(flag) );
1148}
1149
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001150int socket_set_xreuseaddr(int fd)
1151{
1152#ifdef _WIN32
1153 /* on Windows, SO_REUSEADDR is used to indicate that several programs can
1154 * bind to the same port. this is completely different from the Unix
1155 * semantics. instead of SO_EXCLUSIVEADDR to ensure that explicitely prevent
1156 * this.
1157 */
1158 return socket_setoption(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1);
1159#else
1160 return socket_setoption(fd, SOL_SOCKET, SO_REUSEADDR, 1);
1161#endif
1162}
1163
1164
1165int socket_set_oobinline(int fd)
1166{
1167 return socket_setoption(fd, SOL_SOCKET, SO_OOBINLINE, 1);
1168}
1169
David 'Digit' Turner94cf4e22014-01-16 18:12:25 +01001170int socket_set_cork(int fd, int v)
1171{
1172#if defined(SOL_TCP) && defined(TCP_CORK)
1173 return socket_setoption(fd, SOL_TCP, TCP_CORK, v);
1174#else
1175 return 0;
1176#endif
1177}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001178
1179int socket_set_nodelay(int fd)
1180{
1181 return socket_setoption(fd, IPPROTO_TCP, TCP_NODELAY, 1);
1182}
1183
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001184int socket_set_ipv6only(int fd)
1185{
1186/* IPV6_ONLY is only supported since Vista on Windows,
1187 * and the Mingw headers lack its definition anyway.
1188 */
1189#if defined(_WIN32) && !defined(IPV6_V6ONLY)
1190 return 0;
1191#else
1192 return socket_setoption(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1);
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001193#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001194}
1195
1196
1197int socket_get_error(int fd)
1198{
1199 return socket_getoption(fd, SOL_SOCKET, SO_ERROR, -1);
1200}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001201
1202#ifdef _WIN32
1203#include <stdlib.h>
1204
1205static void socket_cleanup(void)
1206{
1207 WSACleanup();
1208}
1209
1210int socket_init(void)
1211{
1212 WSADATA Data;
David 'Digit' Turner7891dd32014-04-28 10:59:47 +02001213 int ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001214
1215 ret = WSAStartup(MAKEWORD(2,2), &Data);
1216 if (ret != 0) {
David 'Digit' Turner7891dd32014-04-28 10:59:47 +02001217 (void) WSAGetLastError();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001218 return -1;
1219 }
1220 atexit(socket_cleanup);
1221 return 0;
1222}
1223
1224#else /* !_WIN32 */
1225
1226int socket_init(void)
1227{
1228 return 0; /* nothing to do on Unix */
1229}
1230
1231#endif /* !_WIN32 */
1232
1233#ifdef _WIN32
1234
1235static void
1236socket_close_handler( void* _fd )
1237{
1238 int fd = (int)_fd;
1239 int ret;
1240 char buff[64];
1241
1242 /* we want to drain the read side of the socket before closing it */
1243 do {
1244 ret = recv( fd, buff, sizeof(buff), 0 );
1245 } while (ret < 0 && WSAGetLastError() == WSAEINTR);
1246
1247 if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
1248 return;
1249
1250 qemu_set_fd_handler( fd, NULL, NULL, NULL );
1251 closesocket( fd );
1252}
1253
1254void
1255socket_close( int fd )
1256{
1257 int old_errno = errno;
1258
1259 shutdown( fd, SD_BOTH );
1260 /* we want to drain the socket before closing it */
1261 qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
1262
1263 errno = old_errno;
1264}
1265
1266#else /* !_WIN32 */
1267
1268#include <unistd.h>
1269
1270void
1271socket_close( int fd )
1272{
1273 int old_errno = errno;
1274
1275 shutdown( fd, SHUT_RDWR );
David 'Digit' Turneraf81d742014-02-03 17:11:18 +01001276 IGNORE_EINTR(close( fd ));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001277
1278 errno = old_errno;
1279}
1280
1281#endif /* !_WIN32 */
1282
1283
1284static int
1285socket_bind_server( int s, const SockAddress* to, SocketType type )
1286{
1287 socket_set_xreuseaddr(s);
1288
1289 if (socket_bind(s, to) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001290 D("could not bind server socket address %s: %s",
1291 sock_address_to_string(to), errno_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001292 goto FAIL;
1293 }
1294
1295 if (type == SOCKET_STREAM) {
1296 if (socket_listen(s, 4) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001297 D("could not listen server socket %s: %s",
1298 sock_address_to_string(to), errno_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001299 goto FAIL;
1300 }
1301 }
1302 return s;
1303
1304FAIL:
1305 socket_close(s);
1306 return -1;
1307}
1308
1309
1310static int
1311socket_connect_client( int s, const SockAddress* to )
1312{
1313 if (socket_connect(s, to) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001314 D( "could not connect client socket to %s: %s\n",
1315 sock_address_to_string(to), errno_str );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001316 socket_close(s);
1317 return -1;
1318 }
1319
1320 socket_set_nonblock( s );
1321 return s;
1322}
1323
1324
1325static int
1326socket_in_server( int address, int port, SocketType type )
1327{
1328 SockAddress addr;
1329 int s;
1330
1331 sock_address_init_inet( &addr, address, port );
1332 s = socket_create_inet( type );
1333 if (s < 0)
1334 return -1;
1335
1336 return socket_bind_server( s, &addr, type );
1337}
1338
1339
1340static int
1341socket_in_client( SockAddress* to, SocketType type )
1342{
1343 int s;
1344
1345 s = socket_create_inet( type );
1346 if (s < 0) return -1;
1347
1348 return socket_connect_client( s, to );
1349}
1350
1351
1352int
1353socket_loopback_server( int port, SocketType type )
1354{
1355 return socket_in_server( SOCK_ADDRESS_INET_LOOPBACK, port, type );
1356}
1357
1358int
1359socket_loopback_client( int port, SocketType type )
1360{
1361 SockAddress addr;
1362
1363 sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, port );
1364 return socket_in_client( &addr, type );
1365}
1366
1367
1368int
1369socket_network_client( const char* host, int port, SocketType type )
1370{
1371 SockAddress addr;
1372
1373 if (sock_address_init_resolve( &addr, host, port, 0) < 0)
1374 return -1;
1375
1376 return socket_in_client( &addr, type );
1377}
1378
1379
1380int
1381socket_anyaddr_server( int port, SocketType type )
1382{
1383 return socket_in_server( SOCK_ADDRESS_INET_ANY, port, type );
1384}
1385
1386int
1387socket_accept_any( int server_fd )
1388{
1389 int fd;
1390
1391 QSOCKET_CALL(fd, accept( server_fd, NULL, 0 ));
1392 if (fd < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001393 D( "could not accept client connection from fd %d: %s",
1394 server_fd, errno_str );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001395 return -1;
1396 }
1397
1398 /* set to non-blocking */
1399 socket_set_nonblock( fd );
1400 return fd;
1401}
1402
1403
1404#if HAVE_UNIX_SOCKETS
1405
1406int
1407socket_unix_server( const char* name, SocketType type )
1408{
1409 SockAddress addr;
1410 int s, ret;
1411
1412 s = socket_create_unix( type );
1413 if (s < 0)
1414 return -1;
1415
1416 sock_address_init_unix( &addr, name );
1417
David 'Digit' Turneraf81d742014-02-03 17:11:18 +01001418 HANDLE_EINTR(unlink(name));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001419
1420 ret = socket_bind_server( s, &addr, type );
1421
1422 sock_address_done( &addr );
1423 return ret;
1424}
1425
1426int
1427socket_unix_client( const char* name, SocketType type )
1428{
1429 SockAddress addr;
1430 int s, ret;
1431
1432 s = socket_create_unix(type);
1433 if (s < 0)
1434 return -1;
1435
1436 sock_address_init_unix( &addr, name );
1437
1438 ret = socket_connect_client( s, &addr );
1439
1440 sock_address_done( &addr );
1441 return ret;
1442}
1443
1444#endif /* HAVE_UNIX_SOCKETS */
1445
1446
1447
1448int
1449socket_pair(int *fd1, int *fd2)
1450{
1451#ifndef _WIN32
1452 int fds[2];
1453 int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
1454
1455 if (!ret) {
1456 socket_set_nonblock(fds[0]);
1457 socket_set_nonblock(fds[1]);
1458 *fd1 = fds[0];
1459 *fd2 = fds[1];
1460 }
1461 return ret;
1462#else /* _WIN32 */
1463 /* on Windows, select() only works with network sockets, which
1464 * means we absolutely cannot use Win32 PIPEs to implement
1465 * socket pairs with the current event loop implementation.
1466 * We're going to do like Cygwin: create a random pair
1467 * of localhost TCP sockets and connect them together
1468 */
1469 int s0, s1, s2, port;
1470 struct sockaddr_in sockin;
1471 socklen_t len;
1472
1473 /* first, create the 'server' socket.
1474 * a port number of 0 means 'any port between 1024 and 5000.
1475 * see Winsock bind() documentation for details */
1476 s0 = socket_loopback_server( 0, SOCK_STREAM );
1477 if (s0 < 0)
1478 return -1;
1479
1480 /* now connect a client socket to it, we first need to
1481 * extract the server socket's port number */
1482 len = sizeof sockin;
1483 if (getsockname(s0, (struct sockaddr*) &sockin, &len) < 0) {
1484 closesocket (s0);
1485 return -1;
1486 }
1487
1488 port = ntohs(sockin.sin_port);
1489 s2 = socket_loopback_client( port, SOCK_STREAM );
1490 if (s2 < 0) {
1491 closesocket(s0);
1492 return -1;
1493 }
1494
1495 /* we need to accept the connection on the server socket
1496 * this will create the second socket for the pair
1497 */
1498 len = sizeof sockin;
1499 s1 = accept(s0, (struct sockaddr*) &sockin, &len);
1500 if (s1 == INVALID_SOCKET) {
1501 closesocket (s0);
1502 closesocket (s2);
1503 return -1;
1504 }
1505 socket_set_nonblock(s1);
1506
1507 /* close server socket */
1508 closesocket(s0);
1509 *fd1 = s1;
1510 *fd2 = s2;
1511 return 0;
1512#endif /* _WIN32 */
1513}
1514
1515
1516
1517int
1518socket_mcast_inet_add_membership( int s, uint32_t ip )
1519{
1520 struct ip_mreq imr;
1521
1522 imr.imr_multiaddr.s_addr = htonl(ip);
1523 imr.imr_interface.s_addr = htonl(INADDR_ANY);
1524
1525 if ( setsockopt( s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001526 (const char *)&imr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001527 sizeof(struct ip_mreq)) < 0 )
1528 {
Andrew Hsieh7f661af2012-05-02 13:24:28 +08001529 return fix_errno();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001530 }
1531 return 0;
1532}
1533
1534int
1535socket_mcast_inet_drop_membership( int s, uint32_t ip )
1536{
1537 struct ip_mreq imr;
1538
1539 imr.imr_multiaddr.s_addr = htonl(ip);
1540 imr.imr_interface.s_addr = htonl(INADDR_ANY);
1541
1542 if ( setsockopt( s, IPPROTO_IP, IP_DROP_MEMBERSHIP,
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001543 (const char *)&imr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001544 sizeof(struct ip_mreq)) < 0 )
1545 {
Andrew Hsieh7f661af2012-05-02 13:24:28 +08001546 return fix_errno();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001547 }
1548 return 0;
1549}
1550
1551int
1552socket_mcast_inet_set_loop( int s, int enabled )
1553{
1554 return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_LOOP, !!enabled );
1555}
1556
1557int
1558socket_mcast_inet_set_ttl( int s, int ttl )
1559{
1560 return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_TTL, ttl );
1561}
1562
1563
1564char*
1565host_name( void )
1566{
1567 static char buf[256]; /* 255 is the max host name length supported by DNS */
1568 int ret;
1569
1570 QSOCKET_CALL(ret, gethostname(buf, sizeof(buf)));
1571
1572 if (ret < 0)
1573 return "localhost";
1574 else
1575 return buf;
1576}
David 'Digit' Turner94cf4e22014-01-16 18:12:25 +01001577
1578
1579// Temporary work-arounds until we get rid of this source file.
1580
1581int qemu_getsockopt(int sock, int level, int optname, void* optval,
1582 size_t* optlen) {
1583 socklen_t len = (socklen_t) *optlen;
1584 int ret = getsockopt(sock, level, optname, (char*)optval, &len);
1585 *optlen = (size_t) len;
1586 return ret;
1587}
1588
1589int qemu_setsockopt(int sock, int level, int optname, const void* optval,
1590 size_t optlen) {
1591 return setsockopt(sock, level, optname, (const char*)optval,
1592 (socklen_t)optlen);
1593}
1594
1595int qemu_recv(int sock, void* buf, size_t len, int flags) {
1596 return recv(sock, buf, len, flags);
1597}