aboutsummaryrefslogtreecommitdiffstats
path: root/sockets.h
blob: 6ce304137968ce4c17bc1e9d2d62af4bb1d41598 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
/* Copyright (C) 2007-2008 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
*/
/* headers to use the BSD sockets */
#ifndef QEMU_SOCKET_H
#define QEMU_SOCKET_H

#include <stddef.h>
#include <stdint.h>
#include <errno.h>

/* we're going to hide the implementation details of sockets behind
 * a simple wrapper interface declared here.
 *
 * all socket operations set the global 'errno' variable on error.
 * this is unlike Winsock which instead modifies another internal
 * variable accessed through WSAGetLastError() and WSASetLastError()
 */

/* the wrapper will convert any Winsock error message into an errno
 * code for you. There are however a few standard Unix error codes
 * that are not defined by the MS C library headers, so we add them
 * here. We use the official Winsock error codes, which are documented
 * even though we don't want to include the Winsock headers
 */
#ifdef _WIN32
#  ifndef EINTR
#    define EINTR        10004
#  endif
#  ifndef EAGAIN
#    define EAGAIN       10035
#  endif
#  ifndef EWOULDBLOCK
#    define EWOULDBLOCK  EAGAIN
#  endif
#  ifndef EINPROGRESS
#    define EINPROGRESS  10036
#  endif
#  ifndef EALREADY
#    define EALREADY     10037
#  endif
#  ifndef EDESTADDRREQ
#    define EDESTADDRREQ 10039
#  endif
#  ifndef EMSGSIZE
#    define EMSGSIZE     10040
#  endif
#  ifndef EPROTOTYPE
#    define EPROTOTYPE   10041
#  endif
#  ifndef ENOPROTOOPT
#    define ENOPROTOOPT  10042
#  endif
#  ifndef EAFNOSUPPORT
#    define EAFNOSUPPORT 10047
#  endif
#  ifndef EADDRINUSE
#    define EADDRINUSE   10048
#  endif
#  ifndef EADDRNOTAVAIL
#    define EADDRNOTAVAIL 10049
#  endif
#  ifndef ENETDOWN
#    define ENETDOWN     10050
#  endif
#  ifndef ENETUNREACH
#    define ENETUNREACH  10051
#  endif
#  ifndef ENETRESET
#    define ENETRESET    10052
#  endif
#  ifndef ECONNABORTED
#    define ECONNABORTED 10053
#  endif
#  ifndef ECONNRESET
#    define ECONNRESET   10054
#  endif
#  ifndef ENOBUFS
#    define ENOBUFS      10055
#  endif
#  ifndef EISCONN
#    define EISCONN      10056
#  endif
#  ifndef ENOTCONN
#    define ENOTCONN     10057
#  endif
#  ifndef ESHUTDOWN
#    define ESHUTDOWN     10058
#  endif
#  ifndef ETOOMANYREFS
#    define ETOOMANYREFS  10059
#  endif
#  ifndef ETIMEDOUT
#    define ETIMEDOUT     10060
#  endif
#  ifndef ECONNREFUSED
#    define ECONNREFUSED  10061
#  endif
#  ifndef ELOOP
#    define ELOOP         10062
#  endif
#  ifndef EHOSTDOWN
#    define EHOSTDOWN     10064
#  endif
#  ifndef EHOSTUNREACH
#    define EHOSTUNREACH  10065
#  endif
#endif /* _WIN32 */

/* Define 'errno_str' as a handy macro to return the string
 * corresponding to a given errno code. On Unix, this is
 * equivalent to strerror(errno), but on Windows, this will
 * take care of Winsock-originated errors as well.
 */
#ifdef _WIN32
  extern const char*  _errno_str(void);
#  define  errno_str   _errno_str()
#else
#  define  errno_str   strerror(errno)
#endif

/* always enable IPv6 sockets for now.
 * the QEMU internal router is not capable of
 * supporting them, but we plan to replace it
 * with something better in the future.
 */
#define  HAVE_IN6_SOCKETS   1

/* Unix sockets are not available on Win32 */
#ifndef _WIN32
#  define  HAVE_UNIX_SOCKETS  1
#endif

/* initialize the socket sub-system. this must be called before
 * using any of the declarations below.
 */
int  socket_init( void );

/* return the name of the current host */
char*  host_name( void );

/* supported socket types */
typedef enum {
    SOCKET_DGRAM = 0,
    SOCKET_STREAM
} SocketType;

/* supported socket families */
typedef enum {
    SOCKET_UNSPEC,
    SOCKET_INET,
    SOCKET_IN6,
    SOCKET_UNIX
} SocketFamily;

/* Generic socket address structure. Note that for Unix
 * sockets, the path is stored in a heap-allocated block,
 * unless the 'owner' field is cleared. If this is the case,
 */
typedef struct {
    SocketFamily  family;
    union {
        struct {
            uint16_t   port;
            uint32_t   address;
        } inet;
        struct {
            uint16_t   port;
            uint8_t    address[16];
        } in6;
        struct {
            int          owner;
            const char*  path;
        } _unix;
    } u;
} SockAddress;

#define  SOCK_ADDRESS_INET_ANY       0x00000000
#define  SOCK_ADDRESS_INET_LOOPBACK  0x7f000001

/* initialize a new IPv4 socket address, the IP address and port are
 * in host endianess.
 */
void  sock_address_init_inet( SockAddress*  a, uint32_t  ip, uint16_t  port );

/* Initialize an IPv6 socket address, the address is in network order
 * and the port in host endianess.
 */
#if HAVE_IN6_SOCKETS
void  sock_address_init_in6 ( SockAddress*  a, const uint8_t*  ip6[16], uint16_t  port );
#endif

/* Intialize a Unix socket address, this will copy the 'path' string into the
 * heap. You need to call sock_address_done() to release the copy
 */
#if HAVE_UNIX_SOCKETS
void  sock_address_init_unix( SockAddress*  a, const char*  path );
#endif

/* Finalize a socket address, only needed for now for Unix addresses */
void  sock_address_done( SockAddress*  a );

int   sock_address_equal( const SockAddress*  a, const SockAddress*  b );

/* return a static string describing the address */
const char*  sock_address_to_string( const SockAddress*  a );

static __inline__
SocketFamily  sock_address_get_family( const SockAddress*  a )
{
    return a->family;
}

/* return the port number of a given socket address, or -1 if it's a Unix one */
int   sock_address_get_port( const SockAddress*  a );

/* set the port number of a given socket address, don't do anything for Unix ones */
void  sock_address_set_port( SockAddress*  a, uint16_t  port );

/* return the path of a given Unix socket, returns NULL for non-Unix ones */
const char*  sock_address_get_path( const SockAddress*  a );

/* return the inet address, or -1 if it's not SOCKET_INET */
int   sock_address_get_ip( const SockAddress*  a );

/* bufprint a socket address into a human-readable string */
char* bufprint_sock_address( char*  p, char*  end, const SockAddress*  a );

/* resolve a hostname or decimal IPv4/IPv6 address into a socket address.
 * returns 0 on success, or -1 on failure. Note that the values or errno
 * set by this function are the following:
 *
 *   EINVAL    : invalid argument
 *   EHOSTDOWN : could not reach DNS server
 *   ENOENT    : no host with this name, or host doesn't have any IP address
 *   ENOMEM    : not enough memory to perform request
 */
int   sock_address_init_resolve( SockAddress*  a,
                                 const char*   hostname,
                                 uint16_t      port,
                                 int           preferIn6 );

int  sock_address_get_numeric_info( SockAddress*  a,
                                    char*         host,
                                    size_t        hostlen,
                                    char*         serv,
                                    size_t        servlen );

/* Support for listing all socket addresses of a given host */
enum {
    SOCKET_LIST_PASSIVE    = (1 << 0),
    SOCKET_LIST_FORCE_INET = (1 << 1),
    SOCKET_LIST_FORCE_IN6  = (1 << 2),
    SOCKET_LIST_DGRAM      = (1 << 3),
};

/* resolve a host and service/port name into a list of SockAddress objects.
 * returns a NULL-terminated array of SockAddress pointers on success,
 * or NULL in case of failure, with the value of errno set to one of the
 * following:
 *
 *    EINVAL    : invalid argument
 *    EHOSTDOWN : could not reach DNS server
 *    ENOENT    : no host with this name, or host doesn't have IP address
 *    ENOMEM    : not enough memory to perform request
 *
 * other system-level errors can also be set depending on the host sockets
 * implementation.
 *
 * This function loops on EINTR so the caller shouldn't have to check for it.
 */
SockAddress**  sock_address_list_create( const char*  hostname,
                                         const char*  port,
                                         unsigned     flags );

/* resolve a string containing host and port name into a list of SockAddress
 * objects. Parameter host_and_port should be in format [host:]port, where
 * 'host' addresses the machine and must be resolvable into an IP address, and
 * 'port' is a decimal numeric value for the port. 'host' is optional, and if
 * ommited, localhost will be used.
 * returns a NULL-terminated array of SockAddress pointers on success,
 * or NULL in case of failure, with the value of errno set to one of the
 * following:
 *
 *    EINVAL    : invalid argument
 *    EHOSTDOWN : could not reach DNS server
 *    ENOENT    : no host with this name, or host doesn't have IP address
 *    ENOMEM    : not enough memory to perform request
 *
 * other system-level errors can also be set depending on the host sockets
 * implementation.
 *
 * This function loops on EINTR so the caller shouldn't have to check for it.
 */
SockAddress**  sock_address_list_create2(const char*  host_and_port,
                                         unsigned     flags );

void sock_address_list_free( SockAddress**  list );

/* create a new socket, return the socket number of -1 on failure */
int  socket_create( SocketFamily  family, SocketType  type );

/* create a new socket intended for IPv4 communication. returns the socket number,
 * or -1 on failure.
 */
int   socket_create_inet( SocketType  type );

/* create a new socket intended for IPv6 communication. returns the socket number,
 * or -1 on failure.
 */
#if HAVE_IN6_SOCKETS
int   socket_create_in6 ( SocketType  type );
#endif

/* create a unix/local domain socket. returns the socket number,
 * or -1 on failure.
 */
#if HAVE_UNIX_SOCKETS
int   socket_create_unix( SocketType  type );
#endif

/* return the type of a given socket */
SocketType  socket_get_type(int  fd);

/* set SO_REUSEADDR on Unix, SO_EXCLUSIVEADDR on Windows */
int  socket_set_xreuseaddr(int  fd);

/* set socket in non-blocking mode */
int  socket_set_nonblock(int fd);

/* set socket in blocking mode */
int  socket_set_blocking(int fd);

/* disable the TCP Nagle algorithm for lower latency */
int  socket_set_nodelay(int fd);

/* send OOB data inline for this socket */
int  socket_set_oobinline(int  fd);

/* force listening to IPv6 interfaces only */
int  socket_set_ipv6only(int  fd);

/* retrieve last socket error code */
int  socket_get_error(int  fd);

/* close an opened socket. Note that this is unlike the Unix 'close' because:
 * - it will properly shutdown the socket in the background
 * - it does not modify errno
 */
void  socket_close( int  fd );

/* the following functions are equivalent to the BSD sockets ones
 */
int   socket_recv    ( int  fd, void*  buf, int  buflen );
int   socket_recvfrom( int  fd, void*  buf, int  buflen, SockAddress*  from );

int   socket_send  ( int  fd, const void*  buf, int  buflen );
int   socket_send_oob( int  fd, const void*  buf, int  buflen );
int   socket_sendto( int  fd, const void*  buf, int  buflen, const SockAddress*  to );

int   socket_connect( int  fd, const SockAddress*  address );
int   socket_bind( int  fd, const SockAddress*  address );
int   socket_get_address( int  fd, SockAddress*  address );
int   socket_get_peer_address( int  fd, SockAddress*  address );
int   socket_listen( int  fd, int  backlog );
int   socket_accept( int  fd, SockAddress*  address );

/* returns the number of bytes that can be read from a socket */
int   socket_can_read( int  fd );

/* this call creates a pair of non-blocking sockets connected
 * to each other. this is equivalent to calling the Unix function:
 * socketpair(AF_LOCAL,SOCK_STREAM,0,&fds)
 *
 * on Windows, this will use a pair of TCP loopback sockets instead
 * returns 0 on success, -1 on error.
 */
int  socket_pair(int  *fd1, int *fd2);

/* create a server socket listening on the host's loopback interface */
int  socket_loopback_server( int  port, SocketType  type );

/* connect to a port on the host's loopback interface */
int  socket_loopback_client( int  port, SocketType  type );

/* create a server socket listening to a Unix domain path */
#if HAVE_UNIX_SOCKETS
int  socket_unix_server( const char*  name, SocketType  type );
#endif

/* create a Unix sockets and connects it to a Unix server */
#if HAVE_UNIX_SOCKETS
int  socket_unix_client( const char*  name, SocketType  type );
#endif

/* create an IPv4 client socket and connect it to a given host */
int  socket_network_client( const char*  host, int  port, SocketType  type );

/* create an IPv4 socket and binds it to a given port of the host's interface */
int  socket_anyaddr_server( int  port, SocketType  type );

/* accept a connection from the host's any interface, return the new socket
 * descriptor or -1 */
int  socket_accept_any( int  server_fd );


int  socket_mcast_inet_add_membership( int  s, uint32_t  ip );
int  socket_mcast_inet_drop_membership( int  s, uint32_t  ip );
int  socket_mcast_inet_set_loop( int  s, int  enabled );
int  socket_mcast_inet_set_ttl( int  s, int  ttl );

#endif /* QEMU_SOCKET_H */