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