blob: 12f925f8ca05194c8a088ef6b5a0c4451a9d5cb3 [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*/
12#include "sockets.h"
13#include "qemu-common.h"
14#include <fcntl.h>
15#include <stddef.h>
16#include "qemu_debug.h"
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070017#include "qemu-char.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080018#include <stdlib.h>
19#include <string.h>
20#include "android/utils/path.h"
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +020021#include "android/utils/debug.h"
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070022#include "android/utils/misc.h"
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +020023
24#define D(...) VERBOSE_PRINT(socket,__VA_ARGS__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080025
26#ifdef _WIN32
27# define xxWIN32_LEAN_AND_MEAN
28# include <windows.h>
29# include <winsock2.h>
30# include <ws2tcpip.h>
31#else /* !_WIN32 */
32# include <sys/ioctl.h>
33# include <sys/socket.h>
34# include <netinet/in.h>
35# include <netinet/tcp.h>
Jack Palevichb489a9b2009-09-15 15:46:33 -070036# ifdef __linux__ /* Recent versions of glibc only define EAI_NODATA, which is an
37 extension to the POSIX standard, if __USE_GNU is defined. */
38# define __USE_GNU
39# include <netdb.h>
40# undef __USE_GNU
41# else /* !__linux__ */
42# include <netdb.h>
43# endif /* !__linux__ */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080044# if HAVE_UNIX_SOCKETS
45# include <sys/un.h>
46# ifndef UNIX_PATH_MAX
47# define UNIX_PATH_MAX (sizeof(((struct sockaddr_un*)0)->sun_path)-1)
48# endif
49# endif
50#endif /* !_WIN32 */
51
52
53
54/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
55 * easily in QEMU since we use SIGALRM to implement periodic timers
56 */
57#ifdef _WIN32
58# define QSOCKET_CALL(_ret,_cmd) \
59 do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
60#else
61# define QSOCKET_CALL(_ret,_cmd) \
David 'Digit' Turner7410e8a2009-05-20 10:57:56 +020062 do { \
63 errno = 0; \
64 do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \
65 } while (0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080066#endif
67
68#ifdef _WIN32
69
70#include <errno.h>
71
72static int winsock_error;
73
74#define WINSOCK_ERRORS_LIST \
75 EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
76 EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
77 EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
78 EE(WSAEINTR,EINTR,"interrupted function call") \
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070079 EE(WSAEALREADY,EALREADY,"operation already in progress") \
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080080 EE(WSAEBADF,EBADF,"bad file descriptor") \
81 EE(WSAEACCES,EACCES,"permission denied") \
82 EE(WSAEFAULT,EFAULT,"bad address") \
83 EE(WSAEINVAL,EINVAL,"invalid argument") \
84 EE(WSAEMFILE,EMFILE,"too many opened files") \
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070085 EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \
86 EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080087 EE(WSAEALREADY,EAGAIN,"operation already in progress") \
88 EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
89 EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
90 EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
91 EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
92 EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
93 EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
94 EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
95 EE(WSAENETDOWN,ENETDOWN,"network is down") \
96 EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
97 EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
98 EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
99 EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
100 EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
101 EE(WSAEISCONN,EISCONN,"socket is already connected") \
102 EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
103 EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
104 EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
105 EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
106 EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
107 EE(WSAELOOP,ELOOP,"cannot translate name") \
108 EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
109 EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
110 EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
111
112typedef struct {
113 int winsock;
114 int unix;
115 const char* string;
116} WinsockError;
117
118static const WinsockError _winsock_errors[] = {
119#define EE(w,u,s) { w, u, s },
120 WINSOCK_ERRORS_LIST
121#undef EE
122 { -1, -1, NULL }
123};
124
125/* this function reads the latest winsock error code and updates
126 * errno to a matching value. It also returns the new value of
127 * errno.
128 */
129static int
130_fix_errno( void )
131{
132 const WinsockError* werr = _winsock_errors;
133 int unix = EINVAL; /* generic error code */
134
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -0700135 winsock_error = WSAGetLastError();
136
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800137 for ( ; werr->string != NULL; werr++ ) {
138 if (werr->winsock == winsock_error) {
139 unix = werr->unix;
140 break;
141 }
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +0200142 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800143 errno = unix;
144 return -1;
145}
146
147static int
148_set_errno( int code )
149{
150 winsock_error = -1;
151 errno = code;
152 return -1;
153}
154
155/* this function returns a string describing the latest Winsock error */
156const char*
157_errno_str(void)
158{
159 const WinsockError* werr = _winsock_errors;
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -0700160 const char* result = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800161
162 for ( ; werr->string; werr++ ) {
163 if (werr->winsock == winsock_error) {
164 result = werr->string;
165 break;
166 }
167 }
168
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -0700169 if (result == NULL) {
170 result = tempstr_format(
171 "Unkown socket error (Winsock=0x%08x) errno=%d: %s",
172 winsock_error, errno, strerror(errno));
173 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800174 return result;
175}
176#else
177static int
178_fix_errno( void )
179{
180 return -1;
181}
182
183static int
184_set_errno( int code )
185{
186 errno = code;
187 return -1;
188}
189#endif
190
191/* socket types */
192
193static int
194socket_family_to_bsd( SocketFamily family )
195{
196 switch (family) {
197 case SOCKET_INET: return AF_INET;
198 case SOCKET_IN6: return AF_INET6;
199#if HAVE_UNIX_SOCKETS
200 case SOCKET_UNIX: return AF_LOCAL;
201#endif
202 default: return -1;
203 }
204}
205
206static int
207socket_type_to_bsd( SocketType type )
208{
209 switch (type) {
210 case SOCKET_DGRAM: return SOCK_DGRAM;
211 case SOCKET_STREAM: return SOCK_STREAM;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700212 default: return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800213 }
214}
215
216static SocketType
217socket_type_from_bsd( int type )
218{
219 switch (type) {
220 case SOCK_DGRAM: return SOCKET_DGRAM;
221 case SOCK_STREAM: return SOCKET_STREAM;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700222 default: return (SocketType) SOCKET_UNSPEC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800223 }
224}
225
226#if 0
227static int
228socket_type_check( SocketType type )
229{
230 return (type == SOCKET_DGRAM || type == SOCKET_STREAM);
231}
232#endif
233
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700234typedef union {
235 struct sockaddr sa[1];
236 struct sockaddr_in in[1];
237#if HAVE_IN6_SOCKETS
238 struct sockaddr_in6 in6[1];
239#endif
240#if HAVE_UNIX_SOCKETS
241 struct sockaddr_un un[1];
242#endif
243} sockaddr_storage;
244
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800245/* socket addresses */
246
247void
248sock_address_init_inet( SockAddress* a, uint32_t ip, uint16_t port )
249{
250 a->family = SOCKET_INET;
251 a->u.inet.port = port;
252 a->u.inet.address = ip;
253}
254
255void
256sock_address_init_in6 ( SockAddress* a, const uint8_t* ip6[16], uint16_t port )
257{
258 a->family = SOCKET_IN6;
259 a->u.in6.port = port;
260 memcpy( a->u.in6.address, ip6, sizeof(a->u.in6.address) );
261}
262
263void
264sock_address_init_unix( SockAddress* a, const char* path )
265{
266 a->family = SOCKET_UNIX;
267 a->u._unix.path = strdup(path ? path : "");
268 a->u._unix.owner = 1;
269}
270
271void sock_address_done( SockAddress* a )
272{
273 if (a->family == SOCKET_UNIX && a->u._unix.owner) {
274 a->u._unix.owner = 0;
275 free((char*)a->u._unix.path);
276 }
277}
278
279static char*
280format_char( char* buf, char* end, int c )
281{
David 'Digit' Turner0b7cd6c2009-07-10 00:54:05 +0200282 if (buf < end) {
283 if (buf+1 == end) {
284 *buf++ = 0;
285 } else {
286 *buf++ = (char) c;
287 *buf = 0;
288 }
289 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800290 return buf;
291}
292
293static char*
294format_str( char* buf, char* end, const char* str )
295{
296 int len = strlen(str);
297 int avail = end - buf;
298
299 if (len > avail)
300 len = avail;
301
302 memcpy( buf, str, len );
303 buf += len;
304
305 if (buf == end)
306 buf[-1] = 0;
307 else
308 buf[0] = 0;
309
310 return buf;
311}
312
313static char*
314format_unsigned( char* buf, char* end, unsigned val )
315{
316 char temp[16];
317 int nn;
318
319 for ( nn = 0; val != 0; nn++ ) {
320 int rem = val % 10;
321 temp[nn] = '0'+rem;
322 val /= 10;
323 }
324
325 if (nn == 0)
326 temp[nn++] = '0';
327
328 while (nn > 0)
329 buf = format_char(buf, end, temp[--nn]);
330
331 return buf;
332}
333
334static char*
335format_hex( char* buf, char* end, unsigned val, int ndigits )
336{
337 int shift = 4*ndigits;
338 static const char hex[16] = "0123456789abcdef";
339
340 while (shift >= 0) {
341 buf = format_char(buf, end, hex[(val >> shift) & 15]);
342 shift -= 4;
343 }
344 return buf;
345}
346
347static char*
348format_ip4( char* buf, char* end, uint32_t ip )
349{
350 buf = format_unsigned( buf, end, (unsigned)(ip >> 24) );
351 buf = format_char( buf, end, '.');
352 buf = format_unsigned( buf, end, (unsigned)((ip >> 16) & 255));
353 buf = format_char( buf, end, '.');
354 buf = format_unsigned( buf, end, (unsigned)((ip >> 8) & 255));
355 buf = format_char( buf, end, '.');
356 buf = format_unsigned( buf, end, (unsigned)(ip & 255));
357 return buf;
358}
359
360static char*
361format_ip6( char* buf, char* end, const uint8_t* ip6 )
362{
363 int nn;
364 for (nn = 0; nn < 8; nn++) {
365 int val = (ip6[0] << 16) | ip6[1];
366 ip6 += 2;
367 if (nn > 0)
368 buf = format_char(buf, end, ':');
369 if (val == 0)
370 continue;
371 buf = format_hex(buf, end, val, 4);
372 }
373 return buf;
374}
375
376const char*
377sock_address_to_string( const SockAddress* a )
378{
379 static char buf0[MAX_PATH];
David 'Digit' Turner0b7cd6c2009-07-10 00:54:05 +0200380 char *buf = buf0, *end = buf + sizeof(buf0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800381
382 switch (a->family) {
383 case SOCKET_INET:
384 buf = format_ip4( buf, end, a->u.inet.address );
385 buf = format_char( buf, end, ':' );
386 buf = format_unsigned( buf, end, (unsigned) a->u.inet.port );
387 break;
388
389 case SOCKET_IN6:
390 buf = format_ip6( buf, end, a->u.in6.address );
391 buf = format_char( buf, end, ':' );
392 buf = format_unsigned( buf, end, (unsigned) a->u.in6.port );
393 break;
394
395 case SOCKET_UNIX:
396 buf = format_str( buf, end, a->u._unix.path );
397 break;
398
399 default:
400 return NULL;
401 }
402
403 return buf0;
404}
405
406int
407sock_address_equal( const SockAddress* a, const SockAddress* b )
408{
409 if (a->family != b->family)
410 return 0;
411
412 switch (a->family) {
413 case SOCKET_INET:
414 return (a->u.inet.address == b->u.inet.address &&
415 a->u.inet.port == b->u.inet.port);
416
417 case SOCKET_IN6:
418 return (!memcmp(a->u.in6.address, b->u.in6.address, 16) &&
419 a->u.in6.port == b->u.in6.port);
420
421 case SOCKET_UNIX:
422 return (!strcmp(a->u._unix.path, b->u._unix.path));
423
424 default:
425 return 0;
426 }
427}
428
429int
430sock_address_get_port( const SockAddress* a )
431{
432 switch (a->family) {
433 case SOCKET_INET:
434 return a->u.inet.port;
435 case SOCKET_IN6:
436 return a->u.in6.port;
437 default:
438 return -1;
439 }
440}
441
442void
443sock_address_set_port( SockAddress* a, uint16_t port )
444{
445 switch (a->family) {
446 case SOCKET_INET:
447 a->u.inet.port = port;
448 break;
449 case SOCKET_IN6:
450 a->u.in6.port = port;
451 break;
452 default:
453 ;
454 }
455}
456
457const char*
458sock_address_get_path( const SockAddress* a )
459{
460 if (a->family == SOCKET_UNIX)
461 return a->u._unix.path;
462 else
463 return NULL;
464}
465
466int
467sock_address_get_ip( const SockAddress* a )
468{
469 if (a->family == SOCKET_INET)
470 return a->u.inet.address;
471
472 return -1;
473}
474
475#if 0
476char*
477bufprint_sock_address( char* p, char* end, const SockAddress* a )
478{
479 switch (a->family) {
480 case SOCKET_INET:
481 {
482 uint32_t ip = a->u.inet.address;
483
484 return bufprint( p, end, "%d.%d.%d.%d:%d",
485 (ip >> 24) & 255, (ip >> 16) & 255,
486 (ip >> 8) & 255, ip & 255,
487 a->u.inet.port );
488 }
489 case SOCKET_IN6:
490 {
491 int nn = 0;
492 const char* column = "";
493 const uint8_t* tab = a->u.in6.address;
494 for (nn = 0; nn < 16; nn += 2) {
495 p = bufprint(p, end, "%s%04x", column, (tab[n] << 8) | tab[n+1]);
496 column = ":";
497 }
498 return bufprint(p, end, ":%d", a->u.in6.port);
499 }
500 case SOCKET_UNIX:
501 {
502 return bufprint(p, end, "%s", a->u._unix.path);
503 }
504 default:
505 return p;
506 }
507}
508#endif
509
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700510static int
511sock_address_to_bsd( const SockAddress* a, sockaddr_storage* paddress, size_t *psize )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800512{
513 switch (a->family) {
514 case SOCKET_INET:
515 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700516 struct sockaddr_in* dst = paddress->in;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800517
518 *psize = sizeof(*dst);
519
520 memset( paddress, 0, *psize );
521
522 dst->sin_family = AF_INET;
523 dst->sin_port = htons(a->u.inet.port);
524 dst->sin_addr.s_addr = htonl(a->u.inet.address);
525 }
526 break;
527
528#if HAVE_IN6_SOCKETS
529 case SOCKET_IN6:
530 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700531 struct sockaddr_in6* dst = paddress->in6;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800532
533 *psize = sizeof(*dst);
534
535 memset( paddress, 0, *psize );
536
537 dst->sin6_family = AF_INET6;
538 dst->sin6_port = htons(a->u.in6.port);
539 memcpy( dst->sin6_addr.s6_addr, a->u.in6.address, 16 );
540 }
541 break;
542#endif /* HAVE_IN6_SOCKETS */
543
544#if HAVE_UNIX_SOCKETS
545 case SOCKET_UNIX:
546 {
547 int slen = strlen(a->u._unix.path);
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700548 struct sockaddr_un* dst = paddress->un;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800549
550 if (slen >= UNIX_PATH_MAX)
551 return -1;
552
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700553 memset( dst, 0, sizeof(*dst) );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800554
555 dst->sun_family = AF_LOCAL;
556 memcpy( dst->sun_path, a->u._unix.path, slen );
557 dst->sun_path[slen] = 0;
558
559 *psize = (char*)&dst->sun_path[slen+1] - (char*)dst;
560 }
561 break;
562#endif /* HAVE_UNIX_SOCKETS */
563
564 default:
565 return _set_errno(EINVAL);
566 }
567
568 return 0;
569}
570
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700571static int
572sock_address_from_bsd( SockAddress* a, const sockaddr_storage* from, size_t fromlen )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800573{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700574 switch (from->sa->sa_family) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800575 case AF_INET:
576 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700577 struct sockaddr_in* src = from->in;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800578
579 if (fromlen < sizeof(*src))
580 return _set_errno(EINVAL);
581
582 a->family = SOCKET_INET;
583 a->u.inet.port = ntohs(src->sin_port);
584 a->u.inet.address = ntohl(src->sin_addr.s_addr);
585 }
586 break;
587
588#ifdef HAVE_IN6_SOCKETS
589 case AF_INET6:
590 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700591 struct sockaddr_in6* src = from->in6;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800592
593 if (fromlen < sizeof(*src))
594 return _set_errno(EINVAL);
595
596 a->family = SOCKET_IN6;
597 a->u.in6.port = ntohs(src->sin6_port);
598 memcpy(a->u.in6.address, src->sin6_addr.s6_addr, 16);
599 }
600 break;
601#endif
602
603#ifdef HAVE_UNIX_SOCKETS
604 case AF_LOCAL:
605 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700606 struct sockaddr_un* src = from->un;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800607 char* end;
608
609 if (fromlen < sizeof(*src))
610 return _set_errno(EINVAL);
611
612 /* check that the path is zero-terminated */
613 end = memchr(src->sun_path, 0, UNIX_PATH_MAX);
614 if (end == NULL)
615 return _set_errno(EINVAL);
616
617 a->family = SOCKET_UNIX;
618 a->u._unix.owner = 1;
619 a->u._unix.path = strdup(src->sun_path);
620 }
621 break;
622#endif
623
624 default:
625 return _set_errno(EINVAL);
626 }
627 return 0;
628}
629
630
631int
632sock_address_init_resolve( SockAddress* a, const char* hostname, uint16_t port, int preferIn6 )
633{
634 struct addrinfo hints[1];
635 struct addrinfo* res;
636 int ret;
637
638 memset(hints, 0, sizeof(hints));
639 hints->ai_family = preferIn6 ? AF_INET6 : AF_UNSPEC;
640
David Turner669c4792009-04-13 17:58:45 -0700641 ret = getaddrinfo(hostname, NULL, hints, &res);
642 if (ret != 0) {
643 int err;
644
645 switch (ret) {
646 case EAI_AGAIN: /* server is down */
647 case EAI_FAIL: /* server is sick */
648 err = EHOSTDOWN;
649 break;
650
Nick Pellyf5be61d2009-04-24 15:28:40 -0700651#ifdef EAI_NODATA
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 }
665 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) {
704 ret = _set_errno(ENOENT);
705 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
755 while (1) {
756 struct addrinfo hints = ai;
757
758 ret = getaddrinfo(hostname, port, &hints, &res);
759 if (ret == 0)
760 break;
761
762 switch (ret) {
763#ifdef EAI_ADDRFAMILY
764 case EAI_ADDRFAMILY:
765#endif
766 case EAI_NODATA:
767 _set_errno(ENOENT);
768 break;
769 case EAI_FAMILY:
770 _set_errno(EAFNOSUPPORT);
771 break;
772 case EAI_AGAIN:
773 _set_errno(EAGAIN);
774 break;
775#ifdef EAI_SYSTEM
776 case EAI_SYSTEM:
777 if (errno == EINTR)
778 continue;
779 break;
780#endif
781 default:
782 _set_errno(EINVAL);
783 }
784 return NULL;
785 }
786
787 /* allocate result list */
788 for (count = 0, e = res; e != NULL; e = e->ai_next)
789 count += 1;
790
791 list = (SockAddress**) qemu_malloc((count+1)*sizeof(SockAddress*));
792 addr = (SockAddress*) qemu_malloc(count*sizeof(SockAddress));
793
794 for (nn = 0, e = res; e != NULL; e = e->ai_next) {
795
796 ret = sock_address_from_bsd(addr, e->ai_addr, e->ai_addrlen);
797 if (ret < 0)
798 continue;
799
800 list[nn++] = addr++;
801 }
802 list[nn] = NULL;
803 freeaddrinfo(res);
804 return list;
805}
806
807void
808sock_address_list_free( SockAddress** list )
809{
810 int nn;
811 SockAddress* addr;
812
813 if (list == NULL)
814 return;
815
816 addr = list[0];
817 for (nn = 0; list[nn] != NULL; nn++) {
818 sock_address_done(list[nn]);
819 list[nn] = NULL;
820 }
821 qemu_free(addr);
822 qemu_free(list);
823}
824
825int
826sock_address_get_numeric_info( SockAddress* a,
827 char* host,
828 size_t hostlen,
829 char* serv,
830 size_t servlen )
831{
832 struct sockaddr* saddr;
833 socklen_t slen;
834 int ret;
835
836 switch (a->family) {
837 case SOCKET_INET:
838 saddr = (struct sockaddr*) &a->u.inet.address;
839 slen = sizeof(a->u.inet.address);
840 break;
841
842#if HAVE_IN6_SOCKET
843 case SOCKET_IN6:
844 saddr = (struct sockaddr*) &a->u.in6.address;
845 slen = sizeof(a->u.in6.address);
846 break;
847#endif
848 default:
849 return _set_errno(EINVAL);
850 }
851
852 ret = getnameinfo( saddr, slen, host, hostlen, serv, servlen,
853 NI_NUMERICHOST | NI_NUMERICSERV );
854
855 switch (ret) {
856 case 0:
857 break;
858 case EAI_AGAIN:
859 ret = EAGAIN;
860 break;
861 default:
862 ret = EINVAL;
863 }
864 return ret;
865}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800866
867int
868socket_create( SocketFamily family, SocketType type )
869{
870 int ret;
871 int sfamily = socket_family_to_bsd(family);
872 int stype = socket_type_to_bsd(type);
873
874 if (sfamily < 0 || stype < 0) {
875 return _set_errno(EINVAL);
876 }
877
878 QSOCKET_CALL(ret, socket(sfamily, stype, 0));
879 if (ret < 0)
880 return _fix_errno();
881
882 return ret;
883}
884
885
886int
887socket_create_inet( SocketType type )
888{
889 return socket_create( SOCKET_INET, type );
890}
891
892#if HAVE_IN6_SOCKETS
893int
894socket_create_in6 ( SocketType type )
895{
896 return socket_create( SOCKET_IN6, type );
897}
898#endif
899
900#if HAVE_UNIX_SOCKETS
901int
902socket_create_unix( SocketType type )
903{
904 return socket_create( SOCKET_UNIX, type );
905}
906#endif
907
908int socket_can_read(int fd)
909{
910#ifdef _WIN32
911 unsigned long opt;
912
913 if (ioctlsocket(fd, FIONREAD, &opt) < 0)
914 return 0;
915
916 return opt;
917#else
918 int opt;
919
920 if (ioctl(fd, FIONREAD, &opt) < 0)
921 return 0;
922
923 return opt;
924#endif
925}
926
927#define SOCKET_CALL(cmd) \
928 int ret; \
929 QSOCKET_CALL(ret, (cmd)); \
930 if (ret < 0) \
931 return _fix_errno(); \
932 return ret; \
933
934int
935socket_send(int fd, const void* buf, int buflen)
936{
937 SOCKET_CALL(send(fd, buf, buflen, 0))
938}
939
940int
941socket_send_oob( int fd, const void* buf, int buflen )
942{
943 SOCKET_CALL(send(fd, buf, buflen, MSG_OOB));
944}
945
946int
947socket_sendto(int fd, const void* buf, int buflen, const SockAddress* to)
948{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700949 sockaddr_storage sa;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800950 socklen_t salen;
951
952 if (sock_address_to_bsd(to, &sa, &salen) < 0)
953 return -1;
954
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700955 SOCKET_CALL(sendto(fd, buf, buflen, 0, sa.sa, salen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800956}
957
958int
959socket_recv(int fd, void* buf, int len)
960{
961 SOCKET_CALL(recv(fd, buf, len, 0));
962}
963
964int
965socket_recvfrom(int fd, void* buf, int len, SockAddress* from)
966{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700967 sockaddr_storage sa;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800968 socklen_t salen = sizeof(sa);
969 int ret;
970
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700971 QSOCKET_CALL(ret,recvfrom(fd,buf,len,0,sa.sa,&salen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800972 if (ret < 0)
973 return _fix_errno();
974
975 if (sock_address_from_bsd(from, &sa, salen) < 0)
976 return -1;
977
978 return ret;
979}
980
981int
982socket_connect( int fd, const SockAddress* address )
983{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700984 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800985 socklen_t addrlen;
986
987 if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
988 return -1;
989
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700990 SOCKET_CALL(connect(fd,addr.sa,addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800991}
992
993int
994socket_bind( int fd, const SockAddress* address )
995{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700996 sockaddr_storage addr;
997 socklen_t addrlen;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800998
999 if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
1000 return -1;
1001
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001002 SOCKET_CALL(bind(fd, addr.sa, addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001003}
1004
1005int
1006socket_get_address( int fd, SockAddress* address )
1007{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001008 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001009 socklen_t addrlen = sizeof(addr);
1010 int ret;
1011
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001012 QSOCKET_CALL(ret, getsockname(fd, addr.sa, &addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001013 if (ret < 0)
1014 return _fix_errno();
1015
1016 return sock_address_from_bsd(address, &addr, addrlen);
1017}
1018
1019int
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001020socket_get_peer_address( int fd, SockAddress* address )
1021{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001022 sockaddr_storage addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001023 socklen_t addrlen = sizeof(addr);
1024 int ret;
1025
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001026 QSOCKET_CALL(ret, getpeername(fd, addr.sa, &addrlen));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001027 if (ret < 0)
1028 return _fix_errno();
1029
1030 return sock_address_from_bsd(address, &addr, addrlen);
1031}
1032
1033int
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001034socket_listen( int fd, int backlog )
1035{
1036 SOCKET_CALL(listen(fd, backlog));
1037}
1038
1039int
1040socket_accept( int fd, SockAddress* address )
1041{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001042 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001043 socklen_t addrlen = sizeof(addr);
1044 int ret;
1045
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001046 QSOCKET_CALL(ret, accept(fd, addr.sa, &addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001047 if (ret < 0)
1048 return _fix_errno();
1049
1050 if (address) {
1051 if (sock_address_from_bsd(address, &addr, addrlen) < 0) {
1052 socket_close(ret);
1053 return -1;
1054 }
1055 }
1056 return ret;
1057}
1058
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001059static int
1060socket_getoption(int fd, int domain, int option, int defaut)
1061{
1062 int ret;
1063 while (1) {
1064#ifdef _WIN32
1065 DWORD opt = (DWORD)-1;
1066#else
1067 int opt = -1;
1068#endif
1069 size_t optlen = sizeof(opt);
1070 ret = getsockopt(fd, domain, option, (char*)&opt, &optlen);
1071 if (ret == 0)
1072 return (int)opt;
1073 if (errno != EINTR)
1074 return defaut;
1075 }
1076#undef OPT_CAST
1077}
1078
1079
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001080SocketType socket_get_type(int fd)
1081{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001082 int so_type = socket_getoption(fd, SOL_SOCKET, SO_TYPE, -1);
1083 return socket_type_from_bsd(so_type);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001084}
1085
1086int socket_set_nonblock(int fd)
1087{
1088#ifdef _WIN32
1089 unsigned long opt = 1;
1090 return ioctlsocket(fd, FIONBIO, &opt);
1091#else
1092 int flags = fcntl(fd, F_GETFL);
1093 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
1094#endif
1095}
1096
1097int socket_set_blocking(int fd)
1098{
1099#ifdef _WIN32
1100 unsigned long opt = 0;
1101 return ioctlsocket(fd, FIONBIO, &opt);
1102#else
1103 int flags = fcntl(fd, F_GETFL);
1104 return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
1105#endif
1106}
1107
1108static int
1109socket_setoption(int fd, int domain, int option, int _flag)
1110{
1111#ifdef _WIN32
1112 DWORD flag = (DWORD) _flag;
1113#else
1114 int flag = _flag;
1115#endif
1116 return setsockopt( fd, domain, option, (const char*)&flag, sizeof(flag) );
1117}
1118
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001119int socket_set_xreuseaddr(int fd)
1120{
1121#ifdef _WIN32
1122 /* on Windows, SO_REUSEADDR is used to indicate that several programs can
1123 * bind to the same port. this is completely different from the Unix
1124 * semantics. instead of SO_EXCLUSIVEADDR to ensure that explicitely prevent
1125 * this.
1126 */
1127 return socket_setoption(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1);
1128#else
1129 return socket_setoption(fd, SOL_SOCKET, SO_REUSEADDR, 1);
1130#endif
1131}
1132
1133
1134int socket_set_oobinline(int fd)
1135{
1136 return socket_setoption(fd, SOL_SOCKET, SO_OOBINLINE, 1);
1137}
1138
1139
1140int socket_set_nodelay(int fd)
1141{
1142 return socket_setoption(fd, IPPROTO_TCP, TCP_NODELAY, 1);
1143}
1144
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001145int socket_set_ipv6only(int fd)
1146{
1147/* IPV6_ONLY is only supported since Vista on Windows,
1148 * and the Mingw headers lack its definition anyway.
1149 */
1150#if defined(_WIN32) && !defined(IPV6_V6ONLY)
1151 return 0;
1152#else
1153 return socket_setoption(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1);
1154#endif
1155}
1156
1157
1158int socket_get_error(int fd)
1159{
1160 return socket_getoption(fd, SOL_SOCKET, SO_ERROR, -1);
1161}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001162
1163#ifdef _WIN32
1164#include <stdlib.h>
1165
1166static void socket_cleanup(void)
1167{
1168 WSACleanup();
1169}
1170
1171int socket_init(void)
1172{
1173 WSADATA Data;
1174 int ret, err;
1175
1176 ret = WSAStartup(MAKEWORD(2,2), &Data);
1177 if (ret != 0) {
1178 err = WSAGetLastError();
1179 return -1;
1180 }
1181 atexit(socket_cleanup);
1182 return 0;
1183}
1184
1185#else /* !_WIN32 */
1186
1187int socket_init(void)
1188{
1189 return 0; /* nothing to do on Unix */
1190}
1191
1192#endif /* !_WIN32 */
1193
1194#ifdef _WIN32
1195
1196static void
1197socket_close_handler( void* _fd )
1198{
1199 int fd = (int)_fd;
1200 int ret;
1201 char buff[64];
1202
1203 /* we want to drain the read side of the socket before closing it */
1204 do {
1205 ret = recv( fd, buff, sizeof(buff), 0 );
1206 } while (ret < 0 && WSAGetLastError() == WSAEINTR);
1207
1208 if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
1209 return;
1210
1211 qemu_set_fd_handler( fd, NULL, NULL, NULL );
1212 closesocket( fd );
1213}
1214
1215void
1216socket_close( int fd )
1217{
1218 int old_errno = errno;
1219
1220 shutdown( fd, SD_BOTH );
1221 /* we want to drain the socket before closing it */
1222 qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
1223
1224 errno = old_errno;
1225}
1226
1227#else /* !_WIN32 */
1228
1229#include <unistd.h>
1230
1231void
1232socket_close( int fd )
1233{
1234 int old_errno = errno;
1235
1236 shutdown( fd, SHUT_RDWR );
1237 close( fd );
1238
1239 errno = old_errno;
1240}
1241
1242#endif /* !_WIN32 */
1243
1244
1245static int
1246socket_bind_server( int s, const SockAddress* to, SocketType type )
1247{
1248 socket_set_xreuseaddr(s);
1249
1250 if (socket_bind(s, to) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001251 D("could not bind server socket address %s: %s",
1252 sock_address_to_string(to), errno_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001253 goto FAIL;
1254 }
1255
1256 if (type == SOCKET_STREAM) {
1257 if (socket_listen(s, 4) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001258 D("could not listen server socket %s: %s",
1259 sock_address_to_string(to), errno_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001260 goto FAIL;
1261 }
1262 }
1263 return s;
1264
1265FAIL:
1266 socket_close(s);
1267 return -1;
1268}
1269
1270
1271static int
1272socket_connect_client( int s, const SockAddress* to )
1273{
1274 if (socket_connect(s, to) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001275 D( "could not connect client socket to %s: %s\n",
1276 sock_address_to_string(to), errno_str );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001277 socket_close(s);
1278 return -1;
1279 }
1280
1281 socket_set_nonblock( s );
1282 return s;
1283}
1284
1285
1286static int
1287socket_in_server( int address, int port, SocketType type )
1288{
1289 SockAddress addr;
1290 int s;
1291
1292 sock_address_init_inet( &addr, address, port );
1293 s = socket_create_inet( type );
1294 if (s < 0)
1295 return -1;
1296
1297 return socket_bind_server( s, &addr, type );
1298}
1299
1300
1301static int
1302socket_in_client( SockAddress* to, SocketType type )
1303{
1304 int s;
1305
1306 s = socket_create_inet( type );
1307 if (s < 0) return -1;
1308
1309 return socket_connect_client( s, to );
1310}
1311
1312
1313int
1314socket_loopback_server( int port, SocketType type )
1315{
1316 return socket_in_server( SOCK_ADDRESS_INET_LOOPBACK, port, type );
1317}
1318
1319int
1320socket_loopback_client( int port, SocketType type )
1321{
1322 SockAddress addr;
1323
1324 sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, port );
1325 return socket_in_client( &addr, type );
1326}
1327
1328
1329int
1330socket_network_client( const char* host, int port, SocketType type )
1331{
1332 SockAddress addr;
1333
1334 if (sock_address_init_resolve( &addr, host, port, 0) < 0)
1335 return -1;
1336
1337 return socket_in_client( &addr, type );
1338}
1339
1340
1341int
1342socket_anyaddr_server( int port, SocketType type )
1343{
1344 return socket_in_server( SOCK_ADDRESS_INET_ANY, port, type );
1345}
1346
1347int
1348socket_accept_any( int server_fd )
1349{
1350 int fd;
1351
1352 QSOCKET_CALL(fd, accept( server_fd, NULL, 0 ));
1353 if (fd < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001354 D( "could not accept client connection from fd %d: %s",
1355 server_fd, errno_str );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001356 return -1;
1357 }
1358
1359 /* set to non-blocking */
1360 socket_set_nonblock( fd );
1361 return fd;
1362}
1363
1364
1365#if HAVE_UNIX_SOCKETS
1366
1367int
1368socket_unix_server( const char* name, SocketType type )
1369{
1370 SockAddress addr;
1371 int s, ret;
1372
1373 s = socket_create_unix( type );
1374 if (s < 0)
1375 return -1;
1376
1377 sock_address_init_unix( &addr, name );
1378
1379 do {
1380 ret = unlink( name );
1381 } while (ret < 0 && errno == EINTR);
1382
1383 ret = socket_bind_server( s, &addr, type );
1384
1385 sock_address_done( &addr );
1386 return ret;
1387}
1388
1389int
1390socket_unix_client( const char* name, SocketType type )
1391{
1392 SockAddress addr;
1393 int s, ret;
1394
1395 s = socket_create_unix(type);
1396 if (s < 0)
1397 return -1;
1398
1399 sock_address_init_unix( &addr, name );
1400
1401 ret = socket_connect_client( s, &addr );
1402
1403 sock_address_done( &addr );
1404 return ret;
1405}
1406
1407#endif /* HAVE_UNIX_SOCKETS */
1408
1409
1410
1411int
1412socket_pair(int *fd1, int *fd2)
1413{
1414#ifndef _WIN32
1415 int fds[2];
1416 int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
1417
1418 if (!ret) {
1419 socket_set_nonblock(fds[0]);
1420 socket_set_nonblock(fds[1]);
1421 *fd1 = fds[0];
1422 *fd2 = fds[1];
1423 }
1424 return ret;
1425#else /* _WIN32 */
1426 /* on Windows, select() only works with network sockets, which
1427 * means we absolutely cannot use Win32 PIPEs to implement
1428 * socket pairs with the current event loop implementation.
1429 * We're going to do like Cygwin: create a random pair
1430 * of localhost TCP sockets and connect them together
1431 */
1432 int s0, s1, s2, port;
1433 struct sockaddr_in sockin;
1434 socklen_t len;
1435
1436 /* first, create the 'server' socket.
1437 * a port number of 0 means 'any port between 1024 and 5000.
1438 * see Winsock bind() documentation for details */
1439 s0 = socket_loopback_server( 0, SOCK_STREAM );
1440 if (s0 < 0)
1441 return -1;
1442
1443 /* now connect a client socket to it, we first need to
1444 * extract the server socket's port number */
1445 len = sizeof sockin;
1446 if (getsockname(s0, (struct sockaddr*) &sockin, &len) < 0) {
1447 closesocket (s0);
1448 return -1;
1449 }
1450
1451 port = ntohs(sockin.sin_port);
1452 s2 = socket_loopback_client( port, SOCK_STREAM );
1453 if (s2 < 0) {
1454 closesocket(s0);
1455 return -1;
1456 }
1457
1458 /* we need to accept the connection on the server socket
1459 * this will create the second socket for the pair
1460 */
1461 len = sizeof sockin;
1462 s1 = accept(s0, (struct sockaddr*) &sockin, &len);
1463 if (s1 == INVALID_SOCKET) {
1464 closesocket (s0);
1465 closesocket (s2);
1466 return -1;
1467 }
1468 socket_set_nonblock(s1);
1469
1470 /* close server socket */
1471 closesocket(s0);
1472 *fd1 = s1;
1473 *fd2 = s2;
1474 return 0;
1475#endif /* _WIN32 */
1476}
1477
1478
1479
1480int
1481socket_mcast_inet_add_membership( int s, uint32_t ip )
1482{
1483 struct ip_mreq imr;
1484
1485 imr.imr_multiaddr.s_addr = htonl(ip);
1486 imr.imr_interface.s_addr = htonl(INADDR_ANY);
1487
1488 if ( setsockopt( s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1489 (const char *)&imr,
1490 sizeof(struct ip_mreq)) < 0 )
1491 {
1492 return _fix_errno();
1493 }
1494 return 0;
1495}
1496
1497int
1498socket_mcast_inet_drop_membership( int s, uint32_t ip )
1499{
1500 struct ip_mreq imr;
1501
1502 imr.imr_multiaddr.s_addr = htonl(ip);
1503 imr.imr_interface.s_addr = htonl(INADDR_ANY);
1504
1505 if ( setsockopt( s, IPPROTO_IP, IP_DROP_MEMBERSHIP,
1506 (const char *)&imr,
1507 sizeof(struct ip_mreq)) < 0 )
1508 {
1509 return _fix_errno();
1510 }
1511 return 0;
1512}
1513
1514int
1515socket_mcast_inet_set_loop( int s, int enabled )
1516{
1517 return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_LOOP, !!enabled );
1518}
1519
1520int
1521socket_mcast_inet_set_ttl( int s, int ttl )
1522{
1523 return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_TTL, ttl );
1524}
1525
1526
1527char*
1528host_name( void )
1529{
1530 static char buf[256]; /* 255 is the max host name length supported by DNS */
1531 int ret;
1532
1533 QSOCKET_CALL(ret, gethostname(buf, sizeof(buf)));
1534
1535 if (ret < 0)
1536 return "localhost";
1537 else
1538 return buf;
1539}