aboutsummaryrefslogtreecommitdiff
path: root/src/libslirp.h
blob: 3caa6f1890595bbd69801b1111c8c88feee8c1da (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
/* SPDX-License-Identifier: BSD-3-Clause */
#ifndef LIBSLIRP_H
#define LIBSLIRP_H

#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <in6addr.h>
#include <basetsd.h>
typedef SSIZE_T slirp_ssize_t;
#ifdef BUILDING_LIBSLIRP
# define SLIRP_EXPORT __declspec(dllexport)
#else
# define SLIRP_EXPORT __declspec(dllimport)
#endif
#else
#include <sys/types.h>
typedef ssize_t slirp_ssize_t;
#include <netinet/in.h>
#include <arpa/inet.h>
#define SLIRP_EXPORT
#endif

#include "libslirp-version.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Opaque structure containing the slirp state */
typedef struct Slirp Slirp;

/* Flags passed to SlirpAddPollCb and to be returned by SlirpGetREventsCb. */
enum {
    SLIRP_POLL_IN = 1 << 0,
    SLIRP_POLL_OUT = 1 << 1,
    SLIRP_POLL_PRI = 1 << 2,
    SLIRP_POLL_ERR = 1 << 3,
    SLIRP_POLL_HUP = 1 << 4,
};

/* Callback for application to get data from the guest */
typedef slirp_ssize_t (*SlirpReadCb)(void *buf, size_t len, void *opaque);
/* Callback for application to send data to the guest */
typedef slirp_ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque);
/* Timer callback */
typedef void (*SlirpTimerCb)(void *opaque);
/* Callback for libslirp to register polling callbacks */
typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque);
/* Callback for libslirp to get polling result */
typedef int (*SlirpGetREventsCb)(int idx, void *opaque);

/* For now libslirp creates only a timer for the IPv6 RA */
typedef enum SlirpTimerId {
    SLIRP_TIMER_RA,
    SLIRP_TIMER_NUM,
} SlirpTimerId;

/*
 * Callbacks from slirp, to be set by the application.
 *
 * The opaque parameter is set to the opaque pointer given in the slirp_new /
 * slirp_init call.
 */
typedef struct SlirpCb {
    /*
     * Send an ethernet frame to the guest network. The opaque parameter is the
     * one given to slirp_init(). If the guest is not ready to receive a frame,
     * the function can just drop the data. TCP will then handle retransmissions
     * at a lower pace.
     * <0 reports an IO error.
     */
    SlirpWriteCb send_packet;
    /* Print a message for an error due to guest misbehavior.  */
    void (*guest_error)(const char *msg, void *opaque);
    /* Return the virtual clock value in nanoseconds */
    int64_t (*clock_get_ns)(void *opaque);
    /* Create a new timer with the given callback and opaque data. Not
     * needed if timer_new_opaque is provided. */
    void *(*timer_new)(SlirpTimerCb cb, void *cb_opaque, void *opaque);
    /* Remove and free a timer */
    void (*timer_free)(void *timer, void *opaque);
    /* Modify a timer to expire at @expire_time (ms) */
    void (*timer_mod)(void *timer, int64_t expire_time, void *opaque);
    /* Register a fd for future polling */
    void (*register_poll_fd)(int fd, void *opaque);
    /* Unregister a fd */
    void (*unregister_poll_fd)(int fd, void *opaque);
    /* Kick the io-thread, to signal that new events may be processed because some TCP buffer
     * can now receive more data, i.e. slirp_socket_can_recv will return 1. */
    void (*notify)(void *opaque);

    /*
     * Fields introduced in SlirpConfig version 4 begin
     */

    /* Initialization has completed and a Slirp* has been created.  */
    void (*init_completed)(Slirp *slirp, void *opaque);
    /* Create a new timer.  When the timer fires, the application passes
     * the SlirpTimerId and cb_opaque to slirp_handle_timer.  */
    void *(*timer_new_opaque)(SlirpTimerId id, void *cb_opaque, void *opaque);
} SlirpCb;

#define SLIRP_CONFIG_VERSION_MIN 1
#define SLIRP_CONFIG_VERSION_MAX 5

typedef struct SlirpConfig {
    /* Version must be provided */
    uint32_t version;
    /*
     * Fields introduced in SlirpConfig version 1 begin
     */
    /* Whether to prevent the guest from accessing the Internet */
    int restricted;
    /* Whether IPv4 is enabled */
    bool in_enabled;
    /* Virtual network for the guest */
    struct in_addr vnetwork;
    /* Mask for the virtual network for the guest */
    struct in_addr vnetmask;
    /* Virtual address for the host exposed to the guest */
    struct in_addr vhost;
    /* Whether IPv6 is enabled */
    bool in6_enabled;
    /* Virtual IPv6 network for the guest */
    struct in6_addr vprefix_addr6;
    /* Len of the virtual IPv6 network for the guest */
    uint8_t vprefix_len;
    /* Virtual address for the host exposed to the guest */
    struct in6_addr vhost6;
    /* Hostname exposed to the guest in DHCP hostname option */
    const char *vhostname;
    /* Hostname exposed to the guest in the DHCP TFTP server name option */
    const char *tftp_server_name;
    /* Path of the files served by TFTP */
    const char *tftp_path;
    /* Boot file name exposed to the guest via DHCP */
    const char *bootfile;
    /* Start of the DHCP range */
    struct in_addr vdhcp_start;
    /* Virtual address for the DNS server exposed to the guest */
    struct in_addr vnameserver;
    /* Virtual IPv6 address for the DNS server exposed to the guest */
    struct in6_addr vnameserver6;
    /* DNS search names exposed to the guest via DHCP */
    const char **vdnssearch;
    /* Domain name exposed to the guest via DHCP */
    const char *vdomainname;
    /* MTU when sending packets to the guest */
    /* Default: IF_MTU_DEFAULT */
    size_t if_mtu;
    /* MRU when receiving packets from the guest */
    /* Default: IF_MRU_DEFAULT */
    size_t if_mru;
    /* Prohibit connecting to 127.0.0.1:* */
    bool disable_host_loopback;
    /*
     * Enable emulation code (*warning*: this code isn't safe, it is not
     * recommended to enable it)
     */
    bool enable_emu;

    /*
     * Fields introduced in SlirpConfig version 2 begin
     */
    /* Address to be used when sending data to the Internet */
    struct sockaddr_in *outbound_addr;
    /* IPv6 Address to be used when sending data to the Internet */
    struct sockaddr_in6 *outbound_addr6;

    /*
     * Fields introduced in SlirpConfig version 3 begin
     */
    /* slirp will not redirect/serve any DNS packet */
    bool disable_dns;

    /*
     * Fields introduced in SlirpConfig version 4 begin
     */
    /* slirp will not reply to any DHCP requests */
    bool disable_dhcp;

    /*
     * Fields introduced in SlirpConfig version 5 begin
     */
    /* Manufacturer ID (IANA Private Enterprise number) */
    uint32_t mfr_id;
    /*
     * MAC address allocated for an out-of-band management controller, to be
     * retrieved through NC-SI.
     */
    uint8_t oob_eth_addr[6];
} SlirpConfig;

/* Create a new instance of a slirp stack */
SLIRP_EXPORT
Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks,
                 void *opaque);
/* slirp_init is deprecated in favor of slirp_new */
SLIRP_EXPORT
Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
                  struct in_addr vnetmask, struct in_addr vhost,
                  bool in6_enabled, struct in6_addr vprefix_addr6,
                  uint8_t vprefix_len, struct in6_addr vhost6,
                  const char *vhostname, const char *tftp_server_name,
                  const char *tftp_path, const char *bootfile,
                  struct in_addr vdhcp_start, struct in_addr vnameserver,
                  struct in6_addr vnameserver6, const char **vdnssearch,
                  const char *vdomainname, const SlirpCb *callbacks,
                  void *opaque);
/* Shut down an instance of a slirp stack */
SLIRP_EXPORT
void slirp_cleanup(Slirp *slirp);

/* This is called by the application when it is about to sleep through poll().
 * *timeout is set to the amount of virtual time (in ms) that the application intends to
 * wait (UINT32_MAX if infinite). slirp_pollfds_fill updates it according to
 * e.g. TCP timers, so the application knows it should sleep a smaller amount of
 * time. slirp_pollfds_fill calls add_poll for each file descriptor
 * that should be monitored along the sleep. The opaque pointer is passed as
 * such to add_poll, and add_poll returns an index. */
SLIRP_EXPORT
void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
                        SlirpAddPollCb add_poll, void *opaque);

/* This is called by the application after sleeping, to report which file
 * descriptors are available. slirp_pollfds_poll calls get_revents on each file
 * descriptor, giving it the index that add_poll returned during the
 * slirp_pollfds_fill call, to know whether the descriptor is available for
 * read/write/etc. (SLIRP_POLL_*)
 * select_error should be passed 1 if poll() returned an error. */
SLIRP_EXPORT
void slirp_pollfds_poll(Slirp *slirp, int select_error,
                        SlirpGetREventsCb get_revents, void *opaque);

/* This is called by the application when the guest emits a packet on the
 * guest network, to be interpreted by slirp. */
SLIRP_EXPORT
void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);

/* This is called by the application when a timer expires, if it provides
 * the timer_new_opaque callback.  It is not needed if the application only
 * uses timer_new. */
SLIRP_EXPORT
void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque);

/* These set up / remove port forwarding between a host port in the real world
 * and the guest network.
 * Note: guest_addr must be in network order, while guest_port must be in host
 * order.
 */
SLIRP_EXPORT
int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
                      int host_port, struct in_addr guest_addr, int guest_port);
SLIRP_EXPORT
int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
                         int host_port);

#define SLIRP_HOSTFWD_UDP 1
#define SLIRP_HOSTFWD_V6ONLY 2
SLIRP_EXPORT
int slirp_add_hostxfwd(Slirp *slirp,
                       const struct sockaddr *haddr, socklen_t haddrlen,
                       const struct sockaddr *gaddr, socklen_t gaddrlen,
                       int flags);
SLIRP_EXPORT
int slirp_remove_hostxfwd(Slirp *slirp,
                          const struct sockaddr *haddr, socklen_t haddrlen,
                          int flags);

/* Set up port forwarding between a port in the guest network and a
 * command running on the host */
SLIRP_EXPORT
int slirp_add_exec(Slirp *slirp, const char *cmdline,
                   struct in_addr *guest_addr, int guest_port);
/* Set up port forwarding between a port in the guest network and a
 * Unix port on the host */
SLIRP_EXPORT
int slirp_add_unix(Slirp *slirp, const char *unixsock,
                   struct in_addr *guest_addr, int guest_port);
/* Set up port forwarding between a port in the guest network and a
 * callback that will receive the data coming from the port */
SLIRP_EXPORT
int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
                       struct in_addr *guest_addr, int guest_port);

/* TODO: rather identify a guestfwd through an opaque pointer instead of through
 * the guest_addr */

/* This is called by the application for a guestfwd, to determine how much data
 * can be received by the forwarded port through a call to slirp_socket_recv. */
SLIRP_EXPORT
size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
                             int guest_port);
/* This is called by the application for a guestfwd, to provide the data to be
 * sent on the forwarded port */
SLIRP_EXPORT
void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
                       const uint8_t *buf, int size);

/* Remove entries added by slirp_add_exec, slirp_add_unix or slirp_add_guestfwd */
SLIRP_EXPORT
int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr,
                          int guest_port);

/* Return a human-readable state of the slirp stack */
SLIRP_EXPORT
char *slirp_connection_info(Slirp *slirp);

/* Return a human-readable state of the NDP/ARP tables */
SLIRP_EXPORT
char *slirp_neighbor_info(Slirp *slirp);

/* Save the slirp state through the write_cb. The opaque pointer is passed as
 * such to the write_cb. */
SLIRP_EXPORT
int slirp_state_save(Slirp *s, SlirpWriteCb write_cb, void *opaque);

/* Returns the version of the slirp state, to be saved along the state */
SLIRP_EXPORT
int slirp_state_version(void);

/* Load the slirp state through the read_cb. The opaque pointer is passed as
 * such to the read_cb. The version should be given as it was obtained from
 * slirp_state_version when slirp_state_save was called. */
SLIRP_EXPORT
int slirp_state_load(Slirp *s, int version_id, SlirpReadCb read_cb,
                     void *opaque);

/* Return the version of the slirp implementation */
SLIRP_EXPORT
const char *slirp_version_string(void);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* LIBSLIRP_H */