xref: /freebsd/usr.sbin/bhyve/libslirp.h (revision 8aac90f18aef7c9eea906c3ff9a001ca7b94f375)
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>
42 typedef 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>
50 typedef 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
57 extern "C" {
58 #endif
59 
60 /* Opaque structure containing the slirp state */
61 typedef struct Slirp Slirp;
62 
63 /* Flags passed to SlirpAddPollCb and to be returned by SlirpGetREventsCb. */
64 enum {
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 */
73 typedef slirp_ssize_t (*SlirpReadCb)(void *buf, size_t len, void *opaque);
74 /* Callback for application to send data to the guest */
75 typedef slirp_ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque);
76 /* Timer callback */
77 typedef void (*SlirpTimerCb)(void *opaque);
78 /* Callback for libslirp to register polling callbacks */
79 typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque);
80 /* Callback for libslirp to get polling result */
81 typedef int (*SlirpGetREventsCb)(int idx, void *opaque);
82 
83 /* For now libslirp creates only a timer for the IPv6 RA */
84 typedef 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  */
95 typedef 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 
137 typedef 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 */
226 SLIRP_EXPORT
227 Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks,
228                  void *opaque);
229 /* slirp_init is deprecated in favor of slirp_new */
230 SLIRP_EXPORT
231 Slirp *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 */
242 SLIRP_EXPORT
243 void 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. */
252 SLIRP_EXPORT
253 void 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. */
262 SLIRP_EXPORT
263 void 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. */
268 SLIRP_EXPORT
269 void 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. */
274 SLIRP_EXPORT
275 void 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. */
279 SLIRP_EXPORT
280 int 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);
282 SLIRP_EXPORT
283 int 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
288 SLIRP_EXPORT
289 int slirp_add_hostxfwd(Slirp *slirp,
290                        const struct sockaddr *haddr, socklen_t haddrlen,
291                        const struct sockaddr *gaddr, socklen_t gaddrlen,
292                        int flags);
293 SLIRP_EXPORT
294 int 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 */
300 SLIRP_EXPORT
301 int 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 */
305 SLIRP_EXPORT
306 int 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 */
310 SLIRP_EXPORT
311 int 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. */
319 SLIRP_EXPORT
320 size_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 */
324 SLIRP_EXPORT
325 void 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 */
329 SLIRP_EXPORT
330 int 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 */
334 SLIRP_EXPORT
335 char *slirp_connection_info(Slirp *slirp);
336 
337 /* Return a human-readable state of the NDP/ARP tables */
338 SLIRP_EXPORT
339 char *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. */
343 SLIRP_EXPORT
344 int 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 */
347 SLIRP_EXPORT
348 int 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. */
353 SLIRP_EXPORT
354 int slirp_state_load(Slirp *s, int version_id, SlirpReadCb read_cb,
355                      void *opaque);
356 
357 /* Return the version of the slirp implementation */
358 SLIRP_EXPORT
359 const char *slirp_version_string(void);
360 
361 #ifdef __cplusplus
362 } /* extern "C" */
363 #endif
364 
365 #endif /* LIBSLIRP_H */
366