1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1995,1996 Danny Gasparovski.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holder nor the names of its
15 *    contributors may be used to endorse or promote products derived
16 *    from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
21 * DANNY GASPAROVSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifndef LIBSLIRP_H
31#define LIBSLIRP_H
32
33#include <stdint.h>
34#include <stdbool.h>
35#include <sys/types.h>
36
37#ifdef _WIN32
38#include <winsock2.h>
39#include <ws2tcpip.h>
40#include <in6addr.h>
41#include <basetsd.h>
42typedef SSIZE_T slirp_ssize_t;
43#ifdef BUILDING_LIBSLIRP
44# define SLIRP_EXPORT __declspec(dllexport)
45#else
46# define SLIRP_EXPORT __declspec(dllimport)
47#endif
48#else
49#include <sys/types.h>
50typedef ssize_t slirp_ssize_t;
51#include <netinet/in.h>
52#include <arpa/inet.h>
53#define SLIRP_EXPORT
54#endif
55
56#ifdef __cplusplus
57extern "C" {
58#endif
59
60/* Opaque structure containing the slirp state */
61typedef struct Slirp Slirp;
62
63/* Flags passed to SlirpAddPollCb and to be returned by SlirpGetREventsCb. */
64enum {
65    SLIRP_POLL_IN = 1 << 0,
66    SLIRP_POLL_OUT = 1 << 1,
67    SLIRP_POLL_PRI = 1 << 2,
68    SLIRP_POLL_ERR = 1 << 3,
69    SLIRP_POLL_HUP = 1 << 4,
70};
71
72/* Callback for application to get data from the guest */
73typedef slirp_ssize_t (*SlirpReadCb)(void *buf, size_t len, void *opaque);
74/* Callback for application to send data to the guest */
75typedef slirp_ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque);
76/* Timer callback */
77typedef void (*SlirpTimerCb)(void *opaque);
78/* Callback for libslirp to register polling callbacks */
79typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque);
80/* Callback for libslirp to get polling result */
81typedef int (*SlirpGetREventsCb)(int idx, void *opaque);
82
83/* For now libslirp creates only a timer for the IPv6 RA */
84typedef enum SlirpTimerId {
85    SLIRP_TIMER_RA,
86    SLIRP_TIMER_NUM,
87} SlirpTimerId;
88
89/*
90 * Callbacks from slirp, to be set by the application.
91 *
92 * The opaque parameter is set to the opaque pointer given in the slirp_new /
93 * slirp_init call.
94 */
95typedef struct SlirpCb {
96    /*
97     * Send an ethernet frame to the guest network. The opaque parameter is the
98     * one given to slirp_init(). If the guest is not ready to receive a frame,
99     * the function can just drop the data. TCP will then handle retransmissions
100     * at a lower pace.
101     * <0 reports an IO error.
102     */
103    SlirpWriteCb send_packet;
104    /* Print a message for an error due to guest misbehavior.  */
105    void (*guest_error)(const char *msg, void *opaque);
106    /* Return the virtual clock value in nanoseconds */
107    int64_t (*clock_get_ns)(void *opaque);
108    /* Create a new timer with the given callback and opaque data. Not
109     * needed if timer_new_opaque is provided. */
110    void *(*timer_new)(SlirpTimerCb cb, void *cb_opaque, void *opaque);
111    /* Remove and free a timer */
112    void (*timer_free)(void *timer, void *opaque);
113    /* Modify a timer to expire at @expire_time (ms) */
114    void (*timer_mod)(void *timer, int64_t expire_time, void *opaque);
115    /* Register a fd for future polling */
116    void (*register_poll_fd)(int fd, void *opaque);
117    /* Unregister a fd */
118    void (*unregister_poll_fd)(int fd, void *opaque);
119    /* Kick the io-thread, to signal that new events may be processed because some TCP buffer
120     * can now receive more data, i.e. slirp_socket_can_recv will return 1. */
121    void (*notify)(void *opaque);
122
123    /*
124     * Fields introduced in SlirpConfig version 4 begin
125     */
126
127    /* Initialization has completed and a Slirp* has been created.  */
128    void (*init_completed)(Slirp *slirp, void *opaque);
129    /* Create a new timer.  When the timer fires, the application passes
130     * the SlirpTimerId and cb_opaque to slirp_handle_timer.  */
131    void *(*timer_new_opaque)(SlirpTimerId id, void *cb_opaque, void *opaque);
132} SlirpCb;
133
134#define SLIRP_CONFIG_VERSION_MIN 1
135#define SLIRP_CONFIG_VERSION_MAX 5
136
137typedef struct SlirpConfig {
138    /* Version must be provided */
139    uint32_t version;
140    /*
141     * Fields introduced in SlirpConfig version 1 begin
142     */
143    /* Whether to prevent the guest from accessing the Internet */
144    int restricted;
145    /* Whether IPv4 is enabled */
146    bool in_enabled;
147    /* Virtual network for the guest */
148    struct in_addr vnetwork;
149    /* Mask for the virtual network for the guest */
150    struct in_addr vnetmask;
151    /* Virtual address for the host exposed to the guest */
152    struct in_addr vhost;
153    /* Whether IPv6 is enabled */
154    bool in6_enabled;
155    /* Virtual IPv6 network for the guest */
156    struct in6_addr vprefix_addr6;
157    /* Len of the virtual IPv6 network for the guest */
158    uint8_t vprefix_len;
159    /* Virtual address for the host exposed to the guest */
160    struct in6_addr vhost6;
161    /* Hostname exposed to the guest in DHCP hostname option */
162    const char *vhostname;
163    /* Hostname exposed to the guest in the DHCP TFTP server name option */
164    const char *tftp_server_name;
165    /* Path of the files served by TFTP */
166    const char *tftp_path;
167    /* Boot file name exposed to the guest via DHCP */
168    const char *bootfile;
169    /* Start of the DHCP range */
170    struct in_addr vdhcp_start;
171    /* Virtual address for the DNS server exposed to the guest */
172    struct in_addr vnameserver;
173    /* Virtual IPv6 address for the DNS server exposed to the guest */
174    struct in6_addr vnameserver6;
175    /* DNS search names exposed to the guest via DHCP */
176    const char **vdnssearch;
177    /* Domain name exposed to the guest via DHCP */
178    const char *vdomainname;
179    /* MTU when sending packets to the guest */
180    /* Default: IF_MTU_DEFAULT */
181    size_t if_mtu;
182    /* MRU when receiving packets from the guest */
183    /* Default: IF_MRU_DEFAULT */
184    size_t if_mru;
185    /* Prohibit connecting to 127.0.0.1:* */
186    bool disable_host_loopback;
187    /*
188     * Enable emulation code (*warning*: this code isn't safe, it is not
189     * recommended to enable it)
190     */
191    bool enable_emu;
192
193    /*
194     * Fields introduced in SlirpConfig version 2 begin
195     */
196    /* Address to be used when sending data to the Internet */
197    struct sockaddr_in *outbound_addr;
198    /* IPv6 Address to be used when sending data to the Internet */
199    struct sockaddr_in6 *outbound_addr6;
200
201    /*
202     * Fields introduced in SlirpConfig version 3 begin
203     */
204    /* slirp will not redirect/serve any DNS packet */
205    bool disable_dns;
206
207    /*
208     * Fields introduced in SlirpConfig version 4 begin
209     */
210    /* slirp will not reply to any DHCP requests */
211    bool disable_dhcp;
212
213    /*
214     * Fields introduced in SlirpConfig version 5 begin
215     */
216    /* Manufacturer ID (IANA Private Enterprise number) */
217    uint32_t mfr_id;
218    /*
219     * MAC address allocated for an out-of-band management controller, to be
220     * retrieved through NC-SI.
221     */
222    uint8_t oob_eth_addr[6];
223} SlirpConfig;
224
225/* Create a new instance of a slirp stack */
226SLIRP_EXPORT
227Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks,
228                 void *opaque);
229/* slirp_init is deprecated in favor of slirp_new */
230SLIRP_EXPORT
231Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
232                  struct in_addr vnetmask, struct in_addr vhost,
233                  bool in6_enabled, struct in6_addr vprefix_addr6,
234                  uint8_t vprefix_len, struct in6_addr vhost6,
235                  const char *vhostname, const char *tftp_server_name,
236                  const char *tftp_path, const char *bootfile,
237                  struct in_addr vdhcp_start, struct in_addr vnameserver,
238                  struct in6_addr vnameserver6, const char **vdnssearch,
239                  const char *vdomainname, const SlirpCb *callbacks,
240                  void *opaque);
241/* Shut down an instance of a slirp stack */
242SLIRP_EXPORT
243void slirp_cleanup(Slirp *slirp);
244
245/* This is called by the application when it is about to sleep through poll().
246 * *timeout is set to the amount of virtual time (in ms) that the application intends to
247 * wait (UINT32_MAX if infinite). slirp_pollfds_fill updates it according to
248 * e.g. TCP timers, so the application knows it should sleep a smaller amount of
249 * time. slirp_pollfds_fill calls add_poll for each file descriptor
250 * that should be monitored along the sleep. The opaque pointer is passed as
251 * such to add_poll, and add_poll returns an index. */
252SLIRP_EXPORT
253void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
254                        SlirpAddPollCb add_poll, void *opaque);
255
256/* This is called by the application after sleeping, to report which file
257 * descriptors are available. slirp_pollfds_poll calls get_revents on each file
258 * descriptor, giving it the index that add_poll returned during the
259 * slirp_pollfds_fill call, to know whether the descriptor is available for
260 * read/write/etc. (SLIRP_POLL_*)
261 * select_error should be passed 1 if poll() returned an error. */
262SLIRP_EXPORT
263void slirp_pollfds_poll(Slirp *slirp, int select_error,
264                        SlirpGetREventsCb get_revents, void *opaque);
265
266/* This is called by the application when the guest emits a packet on the
267 * guest network, to be interpreted by slirp. */
268SLIRP_EXPORT
269void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
270
271/* This is called by the application when a timer expires, if it provides
272 * the timer_new_opaque callback.  It is not needed if the application only
273 * uses timer_new. */
274SLIRP_EXPORT
275void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque);
276
277/* These set up / remove port forwarding between a host port in the real world
278 * and the guest network. */
279SLIRP_EXPORT
280int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
281                      int host_port, struct in_addr guest_addr, int guest_port);
282SLIRP_EXPORT
283int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
284                         int host_port);
285
286#define SLIRP_HOSTFWD_UDP 1
287#define SLIRP_HOSTFWD_V6ONLY 2
288SLIRP_EXPORT
289int slirp_add_hostxfwd(Slirp *slirp,
290                       const struct sockaddr *haddr, socklen_t haddrlen,
291                       const struct sockaddr *gaddr, socklen_t gaddrlen,
292                       int flags);
293SLIRP_EXPORT
294int slirp_remove_hostxfwd(Slirp *slirp,
295                          const struct sockaddr *haddr, socklen_t haddrlen,
296                          int flags);
297
298/* Set up port forwarding between a port in the guest network and a
299 * command running on the host */
300SLIRP_EXPORT
301int slirp_add_exec(Slirp *slirp, const char *cmdline,
302                   struct in_addr *guest_addr, int guest_port);
303/* Set up port forwarding between a port in the guest network and a
304 * Unix port on the host */
305SLIRP_EXPORT
306int slirp_add_unix(Slirp *slirp, const char *unixsock,
307                   struct in_addr *guest_addr, int guest_port);
308/* Set up port forwarding between a port in the guest network and a
309 * callback that will receive the data coming from the port */
310SLIRP_EXPORT
311int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
312                       struct in_addr *guest_addr, int guest_port);
313
314/* TODO: rather identify a guestfwd through an opaque pointer instead of through
315 * the guest_addr */
316
317/* This is called by the application for a guestfwd, to determine how much data
318 * can be received by the forwarded port through a call to slirp_socket_recv. */
319SLIRP_EXPORT
320size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
321                             int guest_port);
322/* This is called by the application for a guestfwd, to provide the data to be
323 * sent on the forwarded port */
324SLIRP_EXPORT
325void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
326                       const uint8_t *buf, int size);
327
328/* Remove entries added by slirp_add_exec, slirp_add_unix or slirp_add_guestfwd */
329SLIRP_EXPORT
330int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr,
331                          int guest_port);
332
333/* Return a human-readable state of the slirp stack */
334SLIRP_EXPORT
335char *slirp_connection_info(Slirp *slirp);
336
337/* Return a human-readable state of the NDP/ARP tables */
338SLIRP_EXPORT
339char *slirp_neighbor_info(Slirp *slirp);
340
341/* Save the slirp state through the write_cb. The opaque pointer is passed as
342 * such to the write_cb. */
343SLIRP_EXPORT
344int slirp_state_save(Slirp *s, SlirpWriteCb write_cb, void *opaque);
345
346/* Returns the version of the slirp state, to be saved along the state */
347SLIRP_EXPORT
348int slirp_state_version(void);
349
350/* Load the slirp state through the read_cb. The opaque pointer is passed as
351 * such to the read_cb. The version should be given as it was obtained from
352 * slirp_state_version when slirp_state_save was called. */
353SLIRP_EXPORT
354int slirp_state_load(Slirp *s, int version_id, SlirpReadCb read_cb,
355                     void *opaque);
356
357/* Return the version of the slirp implementation */
358SLIRP_EXPORT
359const char *slirp_version_string(void);
360
361#ifdef __cplusplus
362} /* extern "C" */
363#endif
364
365#endif /* LIBSLIRP_H */
366