1 /* SPDX-License-Identifier: MIT */
2 /*
3  * libslirp glue
4  *
5  * Copyright (c) 2004-2008 Fabrice Bellard
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 #include "slirp.h"
26 
27 
28 #ifndef _WIN32
29 #include <net/if.h>
30 #endif
31 
32 /* https://gitlab.freedesktop.org/slirp/libslirp/issues/18 */
33 #if defined(__NetBSD__) && defined(if_mtu)
34 #undef if_mtu
35 #endif
36 
37 int slirp_debug;
38 
39 /* Define to 1 if you want KEEPALIVE timers */
40 bool slirp_do_keepalive;
41 
42 /* host loopback address */
43 struct in_addr loopback_addr;
44 /* host loopback network mask */
45 unsigned long loopback_mask;
46 
47 /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
48 static const uint8_t special_ethaddr[ETH_ALEN] = { 0x52, 0x55, 0x00,
49                                                    0x00, 0x00, 0x00 };
50 
51 unsigned curtime;
52 
53 static struct in_addr dns_addr;
54 #ifndef _WIN32
55 static struct in6_addr dns6_addr;
56 #endif
57 static unsigned dns_addr_time;
58 #ifndef _WIN32
59 static unsigned dns6_addr_time;
60 #endif
61 
62 #define TIMEOUT_FAST 2 /* milliseconds */
63 #define TIMEOUT_SLOW 499 /* milliseconds */
64 /* for the aging of certain requests like DNS */
65 #define TIMEOUT_DEFAULT 1000 /* milliseconds */
66 
67 #ifdef _WIN32
68 
get_dns_addr(struct in_addr * pdns_addr)69 int get_dns_addr(struct in_addr *pdns_addr)
70 {
71     FIXED_INFO *FixedInfo = NULL;
72     ULONG BufLen;
73     DWORD ret;
74     IP_ADDR_STRING *pIPAddr;
75     struct in_addr tmp_addr;
76 
77     if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < TIMEOUT_DEFAULT) {
78         *pdns_addr = dns_addr;
79         return 0;
80     }
81 
82     FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
83     BufLen = sizeof(FIXED_INFO);
84 
85     if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
86         if (FixedInfo) {
87             GlobalFree(FixedInfo);
88             FixedInfo = NULL;
89         }
90         FixedInfo = GlobalAlloc(GPTR, BufLen);
91     }
92 
93     if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
94         printf("GetNetworkParams failed. ret = %08x\n", (unsigned)ret);
95         if (FixedInfo) {
96             GlobalFree(FixedInfo);
97             FixedInfo = NULL;
98         }
99         return -1;
100     }
101 
102     pIPAddr = &(FixedInfo->DnsServerList);
103     inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
104     *pdns_addr = tmp_addr;
105     dns_addr = tmp_addr;
106     dns_addr_time = curtime;
107     if (FixedInfo) {
108         GlobalFree(FixedInfo);
109         FixedInfo = NULL;
110     }
111     return 0;
112 }
113 
get_dns6_addr(struct in6_addr * pdns6_addr,uint32_t * scope_id)114 int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
115 {
116     return -1;
117 }
118 
winsock_cleanup(void)119 static void winsock_cleanup(void)
120 {
121     WSACleanup();
122 }
123 
124 #else
125 
get_dns_addr_cached(void * pdns_addr,void * cached_addr,socklen_t addrlen,struct stat * cached_stat,unsigned * cached_time)126 static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
127                                socklen_t addrlen, struct stat *cached_stat,
128                                unsigned *cached_time)
129 {
130     struct stat old_stat;
131     if (curtime - *cached_time < TIMEOUT_DEFAULT) {
132         memcpy(pdns_addr, cached_addr, addrlen);
133         return 0;
134     }
135     old_stat = *cached_stat;
136     if (stat("/etc/resolv.conf", cached_stat) != 0) {
137         return -1;
138     }
139     if (cached_stat->st_dev == old_stat.st_dev &&
140         cached_stat->st_ino == old_stat.st_ino &&
141         cached_stat->st_size == old_stat.st_size &&
142         cached_stat->st_mtime == old_stat.st_mtime) {
143         memcpy(pdns_addr, cached_addr, addrlen);
144         return 0;
145     }
146     return 1;
147 }
148 
get_dns_addr_resolv_conf(int af,void * pdns_addr,void * cached_addr,socklen_t addrlen,uint32_t * scope_id,unsigned * cached_time)149 static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
150                                     socklen_t addrlen, uint32_t *scope_id,
151                                     unsigned *cached_time)
152 {
153     char buff[512];
154     char buff2[257];
155     FILE *f;
156     int found = 0;
157     void *tmp_addr = alloca(addrlen);
158     unsigned if_index;
159 
160     f = fopen("/etc/resolv.conf", "r");
161     if (!f)
162         return -1;
163 
164     DEBUG_MISC("IP address of your DNS(s):");
165     while (fgets(buff, 512, f) != NULL) {
166         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
167             char *c = strchr(buff2, '%');
168             if (c) {
169                 if_index = if_nametoindex(c + 1);
170                 *c = '\0';
171             } else {
172                 if_index = 0;
173             }
174 
175             if (!inet_pton(af, buff2, tmp_addr)) {
176                 continue;
177             }
178             /* If it's the first one, set it to dns_addr */
179             if (!found) {
180                 memcpy(pdns_addr, tmp_addr, addrlen);
181                 memcpy(cached_addr, tmp_addr, addrlen);
182                 if (scope_id) {
183                     *scope_id = if_index;
184                 }
185                 *cached_time = curtime;
186             }
187 
188             if (++found > 3) {
189                 DEBUG_MISC("  (more)");
190                 break;
191             } else if (slirp_debug & DBG_MISC) {
192                 char s[INET6_ADDRSTRLEN];
193                 const char *res = inet_ntop(af, tmp_addr, s, sizeof(s));
194                 if (!res) {
195                     res = "  (string conversion error)";
196                 }
197                 DEBUG_MISC("  %s", res);
198             }
199         }
200     }
201     fclose(f);
202     if (!found)
203         return -1;
204     return 0;
205 }
206 
get_dns_addr(struct in_addr * pdns_addr)207 int get_dns_addr(struct in_addr *pdns_addr)
208 {
209     static struct stat dns_addr_stat;
210 
211     if (dns_addr.s_addr != 0) {
212         int ret;
213         ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr),
214                                   &dns_addr_stat, &dns_addr_time);
215         if (ret <= 0) {
216             return ret;
217         }
218     }
219     return get_dns_addr_resolv_conf(AF_INET, pdns_addr, &dns_addr,
220                                     sizeof(dns_addr), NULL, &dns_addr_time);
221 }
222 
get_dns6_addr(struct in6_addr * pdns6_addr,uint32_t * scope_id)223 int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
224 {
225     static struct stat dns6_addr_stat;
226 
227     if (!in6_zero(&dns6_addr)) {
228         int ret;
229         ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr),
230                                   &dns6_addr_stat, &dns6_addr_time);
231         if (ret <= 0) {
232             return ret;
233         }
234     }
235     return get_dns_addr_resolv_conf(AF_INET6, pdns6_addr, &dns6_addr,
236                                     sizeof(dns6_addr), scope_id,
237                                     &dns6_addr_time);
238 }
239 
240 #endif
241 
slirp_init_once(void)242 static void slirp_init_once(void)
243 {
244     static int initialized;
245     const char *debug;
246 #ifdef _WIN32
247     WSADATA Data;
248 #endif
249 
250     if (initialized) {
251         return;
252     }
253     initialized = 1;
254 
255 #ifdef _WIN32
256     WSAStartup(MAKEWORD(2, 0), &Data);
257     atexit(winsock_cleanup);
258 #endif
259 
260     loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
261     loopback_mask = htonl(IN_CLASSA_NET);
262 
263     debug = g_getenv("SLIRP_DEBUG");
264     if (debug) {
265         const GDebugKey keys[] = {
266             { "call", DBG_CALL },
267             { "misc", DBG_MISC },
268             { "error", DBG_ERROR },
269             { "tftp", DBG_TFTP },
270         };
271         slirp_debug = g_parse_debug_string(debug, keys, G_N_ELEMENTS(keys));
272     }
273 }
274 
slirp_new(const SlirpConfig * cfg,const SlirpCb * callbacks,void * opaque)275 Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque)
276 {
277     Slirp *slirp;
278 
279     g_return_val_if_fail(cfg != NULL, NULL);
280     g_return_val_if_fail(cfg->version >= SLIRP_CONFIG_VERSION_MIN, NULL);
281     g_return_val_if_fail(cfg->version <= SLIRP_CONFIG_VERSION_MAX, NULL);
282     g_return_val_if_fail(cfg->if_mtu >= IF_MTU_MIN || cfg->if_mtu == 0, NULL);
283     g_return_val_if_fail(cfg->if_mtu <= IF_MTU_MAX, NULL);
284     g_return_val_if_fail(cfg->if_mru >= IF_MRU_MIN || cfg->if_mru == 0, NULL);
285     g_return_val_if_fail(cfg->if_mru <= IF_MRU_MAX, NULL);
286     g_return_val_if_fail(!cfg->bootfile ||
287                          (strlen(cfg->bootfile) <
288                           G_SIZEOF_MEMBER(struct bootp_t, bp_file)), NULL);
289 
290     slirp = g_malloc0(sizeof(Slirp));
291 
292     slirp_init_once();
293 
294     slirp->opaque = opaque;
295     slirp->cb = callbacks;
296     slirp->grand = g_rand_new();
297     slirp->restricted = cfg->restricted;
298 
299     slirp->in_enabled = cfg->in_enabled;
300     slirp->in6_enabled = cfg->in6_enabled;
301 
302     if_init(slirp);
303     ip_init(slirp);
304     ip6_init(slirp);
305 
306     m_init(slirp);
307 
308     slirp->vnetwork_addr = cfg->vnetwork;
309     slirp->vnetwork_mask = cfg->vnetmask;
310     slirp->vhost_addr = cfg->vhost;
311     slirp->vprefix_addr6 = cfg->vprefix_addr6;
312     slirp->vprefix_len = cfg->vprefix_len;
313     slirp->vhost_addr6 = cfg->vhost6;
314     if (cfg->vhostname) {
315         slirp_pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
316                       cfg->vhostname);
317     }
318     slirp->tftp_prefix = g_strdup(cfg->tftp_path);
319     slirp->bootp_filename = g_strdup(cfg->bootfile);
320     slirp->vdomainname = g_strdup(cfg->vdomainname);
321     slirp->vdhcp_startaddr = cfg->vdhcp_start;
322     slirp->vnameserver_addr = cfg->vnameserver;
323     slirp->vnameserver_addr6 = cfg->vnameserver6;
324     slirp->tftp_server_name = g_strdup(cfg->tftp_server_name);
325 
326     if (cfg->vdnssearch) {
327         translate_dnssearch(slirp, cfg->vdnssearch);
328     }
329     slirp->if_mtu = cfg->if_mtu == 0 ? IF_MTU_DEFAULT : cfg->if_mtu;
330     slirp->if_mru = cfg->if_mru == 0 ? IF_MRU_DEFAULT : cfg->if_mru;
331     slirp->disable_host_loopback = cfg->disable_host_loopback;
332     slirp->enable_emu = cfg->enable_emu;
333 
334     if (cfg->version >= 2) {
335         slirp->outbound_addr = cfg->outbound_addr;
336         slirp->outbound_addr6 = cfg->outbound_addr6;
337     } else {
338         slirp->outbound_addr = NULL;
339         slirp->outbound_addr6 = NULL;
340     }
341     return slirp;
342 }
343 
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)344 Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
345                   struct in_addr vnetmask, struct in_addr vhost,
346                   bool in6_enabled, struct in6_addr vprefix_addr6,
347                   uint8_t vprefix_len, struct in6_addr vhost6,
348                   const char *vhostname, const char *tftp_server_name,
349                   const char *tftp_path, const char *bootfile,
350                   struct in_addr vdhcp_start, struct in_addr vnameserver,
351                   struct in6_addr vnameserver6, const char **vdnssearch,
352                   const char *vdomainname, const SlirpCb *callbacks,
353                   void *opaque)
354 {
355     SlirpConfig cfg;
356     memset(&cfg, 0, sizeof(cfg));
357     cfg.version = 1;
358     cfg.restricted = restricted;
359     cfg.in_enabled = in_enabled;
360     cfg.vnetwork = vnetwork;
361     cfg.vnetmask = vnetmask;
362     cfg.vhost = vhost;
363     cfg.in6_enabled = in6_enabled;
364     cfg.vprefix_addr6 = vprefix_addr6;
365     cfg.vprefix_len = vprefix_len;
366     cfg.vhost6 = vhost6;
367     cfg.vhostname = vhostname;
368     cfg.tftp_server_name = tftp_server_name;
369     cfg.tftp_path = tftp_path;
370     cfg.bootfile = bootfile;
371     cfg.vdhcp_start = vdhcp_start;
372     cfg.vnameserver = vnameserver;
373     cfg.vnameserver6 = vnameserver6;
374     cfg.vdnssearch = vdnssearch;
375     cfg.vdomainname = vdomainname;
376     return slirp_new(&cfg, callbacks, opaque);
377 }
378 
slirp_cleanup(Slirp * slirp)379 void slirp_cleanup(Slirp *slirp)
380 {
381     struct gfwd_list *e, *next;
382 
383     for (e = slirp->guestfwd_list; e; e = next) {
384         next = e->ex_next;
385         g_free(e->ex_exec);
386         g_free(e->ex_unix);
387         g_free(e);
388     }
389 
390     ip_cleanup(slirp);
391     ip6_cleanup(slirp);
392     m_cleanup(slirp);
393 
394     g_rand_free(slirp->grand);
395 
396     g_free(slirp->vdnssearch);
397     g_free(slirp->tftp_prefix);
398     g_free(slirp->bootp_filename);
399     g_free(slirp->vdomainname);
400     g_free(slirp);
401 }
402 
403 #define CONN_CANFSEND(so) \
404     (((so)->so_state & (SS_FCANTSENDMORE | SS_ISFCONNECTED)) == SS_ISFCONNECTED)
405 #define CONN_CANFRCV(so) \
406     (((so)->so_state & (SS_FCANTRCVMORE | SS_ISFCONNECTED)) == SS_ISFCONNECTED)
407 
slirp_update_timeout(Slirp * slirp,uint32_t * timeout)408 static void slirp_update_timeout(Slirp *slirp, uint32_t *timeout)
409 {
410     uint32_t t;
411 
412     if (*timeout <= TIMEOUT_FAST) {
413         return;
414     }
415 
416     t = MIN(1000, *timeout);
417 
418     /* If we have tcp timeout with slirp, then we will fill @timeout with
419      * more precise value.
420      */
421     if (slirp->time_fasttimo) {
422         *timeout = TIMEOUT_FAST;
423         return;
424     }
425     if (slirp->do_slowtimo) {
426         t = MIN(TIMEOUT_SLOW, t);
427     }
428     *timeout = t;
429 }
430 
slirp_pollfds_fill(Slirp * slirp,uint32_t * timeout,SlirpAddPollCb add_poll,void * opaque)431 void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
432                         SlirpAddPollCb add_poll, void *opaque)
433 {
434     struct socket *so, *so_next;
435 
436     /*
437      * First, TCP sockets
438      */
439 
440     /*
441      * *_slowtimo needs calling if there are IP fragments
442      * in the fragment queue, or there are TCP connections active
443      */
444     slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) ||
445                           (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
446 
447     for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) {
448         int events = 0;
449 
450         so_next = so->so_next;
451 
452         so->pollfds_idx = -1;
453 
454         /*
455          * See if we need a tcp_fasttimo
456          */
457         if (slirp->time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) {
458             slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */
459         }
460 
461         /*
462          * NOFDREF can include still connecting to local-host,
463          * newly socreated() sockets etc. Don't want to select these.
464          */
465         if (so->so_state & SS_NOFDREF || so->s == -1) {
466             continue;
467         }
468 
469         /*
470          * Set for reading sockets which are accepting
471          */
472         if (so->so_state & SS_FACCEPTCONN) {
473             so->pollfds_idx = add_poll(
474                 so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
475             continue;
476         }
477 
478         /*
479          * Set for writing sockets which are connecting
480          */
481         if (so->so_state & SS_ISFCONNECTING) {
482             so->pollfds_idx =
483                 add_poll(so->s, SLIRP_POLL_OUT | SLIRP_POLL_ERR, opaque);
484             continue;
485         }
486 
487         /*
488          * Set for writing if we are connected, can send more, and
489          * we have something to send
490          */
491         if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
492             events |= SLIRP_POLL_OUT | SLIRP_POLL_ERR;
493         }
494 
495         /*
496          * Set for reading (and urgent data) if we are connected, can
497          * receive more, and we have room for it XXX /2 ?
498          */
499         if (CONN_CANFRCV(so) &&
500             (so->so_snd.sb_cc < (so->so_snd.sb_datalen / 2))) {
501             events |= SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR |
502                       SLIRP_POLL_PRI;
503         }
504 
505         if (events) {
506             so->pollfds_idx = add_poll(so->s, events, opaque);
507         }
508     }
509 
510     /*
511      * UDP sockets
512      */
513     for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) {
514         so_next = so->so_next;
515 
516         so->pollfds_idx = -1;
517 
518         /*
519          * See if it's timed out
520          */
521         if (so->so_expire) {
522             if (so->so_expire <= curtime) {
523                 udp_detach(so);
524                 continue;
525             } else {
526                 slirp->do_slowtimo = true; /* Let socket expire */
527             }
528         }
529 
530         /*
531          * When UDP packets are received from over the
532          * link, they're sendto()'d straight away, so
533          * no need for setting for writing
534          * Limit the number of packets queued by this session
535          * to 4.  Note that even though we try and limit this
536          * to 4 packets, the session could have more queued
537          * if the packets needed to be fragmented
538          * (XXX <= 4 ?)
539          */
540         if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
541             so->pollfds_idx = add_poll(
542                 so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
543         }
544     }
545 
546     /*
547      * ICMP sockets
548      */
549     for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) {
550         so_next = so->so_next;
551 
552         so->pollfds_idx = -1;
553 
554         /*
555          * See if it's timed out
556          */
557         if (so->so_expire) {
558             if (so->so_expire <= curtime) {
559                 icmp_detach(so);
560                 continue;
561             } else {
562                 slirp->do_slowtimo = true; /* Let socket expire */
563             }
564         }
565 
566         if (so->so_state & SS_ISFCONNECTED) {
567             so->pollfds_idx = add_poll(
568                 so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
569         }
570     }
571 
572     slirp_update_timeout(slirp, timeout);
573 }
574 
slirp_pollfds_poll(Slirp * slirp,int select_error,SlirpGetREventsCb get_revents,void * opaque)575 void slirp_pollfds_poll(Slirp *slirp, int select_error,
576                         SlirpGetREventsCb get_revents, void *opaque)
577 {
578     struct socket *so, *so_next;
579     int ret;
580 
581     curtime = slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS;
582 
583     /*
584      * See if anything has timed out
585      */
586     if (slirp->time_fasttimo &&
587         ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) {
588         tcp_fasttimo(slirp);
589         slirp->time_fasttimo = 0;
590     }
591     if (slirp->do_slowtimo &&
592         ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) {
593         ip_slowtimo(slirp);
594         tcp_slowtimo(slirp);
595         slirp->last_slowtimo = curtime;
596     }
597 
598     /*
599      * Check sockets
600      */
601     if (!select_error) {
602         /*
603          * Check TCP sockets
604          */
605         for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) {
606             int revents;
607 
608             so_next = so->so_next;
609 
610             revents = 0;
611             if (so->pollfds_idx != -1) {
612                 revents = get_revents(so->pollfds_idx, opaque);
613             }
614 
615             if (so->so_state & SS_NOFDREF || so->s == -1) {
616                 continue;
617             }
618 
619             /*
620              * Check for URG data
621              * This will soread as well, so no need to
622              * test for SLIRP_POLL_IN below if this succeeds
623              */
624             if (revents & SLIRP_POLL_PRI) {
625                 ret = sorecvoob(so);
626                 if (ret < 0) {
627                     /* Socket error might have resulted in the socket being
628                      * removed, do not try to do anything more with it. */
629                     continue;
630                 }
631             }
632             /*
633              * Check sockets for reading
634              */
635             else if (revents &
636                      (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR)) {
637                 /*
638                  * Check for incoming connections
639                  */
640                 if (so->so_state & SS_FACCEPTCONN) {
641                     tcp_connect(so);
642                     continue;
643                 } /* else */
644                 ret = soread(so);
645 
646                 /* Output it if we read something */
647                 if (ret > 0) {
648                     tcp_output(sototcpcb(so));
649                 }
650                 if (ret < 0) {
651                     /* Socket error might have resulted in the socket being
652                      * removed, do not try to do anything more with it. */
653                     continue;
654                 }
655             }
656 
657             /*
658              * Check sockets for writing
659              */
660             if (!(so->so_state & SS_NOFDREF) &&
661                 (revents & (SLIRP_POLL_OUT | SLIRP_POLL_ERR))) {
662                 /*
663                  * Check for non-blocking, still-connecting sockets
664                  */
665                 if (so->so_state & SS_ISFCONNECTING) {
666                     /* Connected */
667                     so->so_state &= ~SS_ISFCONNECTING;
668 
669                     ret = send(so->s, (const void *)&ret, 0, 0);
670                     if (ret < 0) {
671                         /* XXXXX Must fix, zero bytes is a NOP */
672                         if (errno == EAGAIN || errno == EWOULDBLOCK ||
673                             errno == EINPROGRESS || errno == ENOTCONN) {
674                             continue;
675                         }
676 
677                         /* else failed */
678                         so->so_state &= SS_PERSISTENT_MASK;
679                         so->so_state |= SS_NOFDREF;
680                     }
681                     /* else so->so_state &= ~SS_ISFCONNECTING; */
682 
683                     /*
684                      * Continue tcp_input
685                      */
686                     tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
687                               so->so_ffamily);
688                     /* continue; */
689                 } else {
690                     ret = sowrite(so);
691                     if (ret > 0) {
692                         /* Call tcp_output in case we need to send a window
693                          * update to the guest, otherwise it will be stuck
694                          * until it sends a window probe. */
695                         tcp_output(sototcpcb(so));
696                     }
697                 }
698             }
699         }
700 
701         /*
702          * Now UDP sockets.
703          * Incoming packets are sent straight away, they're not buffered.
704          * Incoming UDP data isn't buffered either.
705          */
706         for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) {
707             int revents;
708 
709             so_next = so->so_next;
710 
711             revents = 0;
712             if (so->pollfds_idx != -1) {
713                 revents = get_revents(so->pollfds_idx, opaque);
714             }
715 
716             if (so->s != -1 &&
717                 (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
718                 sorecvfrom(so);
719             }
720         }
721 
722         /*
723          * Check incoming ICMP relies.
724          */
725         for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) {
726             int revents;
727 
728             so_next = so->so_next;
729 
730             revents = 0;
731             if (so->pollfds_idx != -1) {
732                 revents = get_revents(so->pollfds_idx, opaque);
733             }
734 
735             if (so->s != -1 &&
736                 (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
737                 icmp_receive(so);
738             }
739         }
740     }
741 
742     if_start(slirp);
743 }
744 
arp_input(Slirp * slirp,const uint8_t * pkt,int pkt_len)745 static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
746 {
747     const struct slirp_arphdr *ah =
748         (const struct slirp_arphdr *)(pkt + ETH_HLEN);
749     uint8_t arp_reply[MAX(ETH_HLEN + sizeof(struct slirp_arphdr), 64)];
750     struct ethhdr *reh = (struct ethhdr *)arp_reply;
751     struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + ETH_HLEN);
752     int ar_op;
753     struct gfwd_list *ex_ptr;
754 
755     if (!slirp->in_enabled) {
756         return;
757     }
758 
759     if (pkt_len < ETH_HLEN + sizeof(struct slirp_arphdr)) {
760         return; /* packet too short */
761     }
762 
763     ar_op = ntohs(ah->ar_op);
764     switch (ar_op) {
765     case ARPOP_REQUEST:
766         if (ah->ar_tip == ah->ar_sip) {
767             /* Gratuitous ARP */
768             arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
769             return;
770         }
771 
772         if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
773             slirp->vnetwork_addr.s_addr) {
774             if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
775                 ah->ar_tip == slirp->vhost_addr.s_addr)
776                 goto arp_ok;
777             /* TODO: IPv6 */
778             for (ex_ptr = slirp->guestfwd_list; ex_ptr;
779                  ex_ptr = ex_ptr->ex_next) {
780                 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
781                     goto arp_ok;
782             }
783             return;
784         arp_ok:
785             memset(arp_reply, 0, sizeof(arp_reply));
786 
787             arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
788 
789             /* ARP request for alias/dns mac address */
790             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
791             memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
792             memcpy(&reh->h_source[2], &ah->ar_tip, 4);
793             reh->h_proto = htons(ETH_P_ARP);
794 
795             rah->ar_hrd = htons(1);
796             rah->ar_pro = htons(ETH_P_IP);
797             rah->ar_hln = ETH_ALEN;
798             rah->ar_pln = 4;
799             rah->ar_op = htons(ARPOP_REPLY);
800             memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
801             rah->ar_sip = ah->ar_tip;
802             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
803             rah->ar_tip = ah->ar_sip;
804             slirp_send_packet_all(slirp, arp_reply, sizeof(arp_reply));
805         }
806         break;
807     case ARPOP_REPLY:
808         arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
809         break;
810     default:
811         break;
812     }
813 }
814 
slirp_input(Slirp * slirp,const uint8_t * pkt,int pkt_len)815 void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
816 {
817     struct mbuf *m;
818     int proto;
819 
820     if (pkt_len < ETH_HLEN)
821         return;
822 
823     proto = (((uint16_t)pkt[12]) << 8) + pkt[13];
824     switch (proto) {
825     case ETH_P_ARP:
826         arp_input(slirp, pkt, pkt_len);
827         break;
828     case ETH_P_IP:
829     case ETH_P_IPV6:
830         m = m_get(slirp);
831         if (!m)
832             return;
833         /* Note: we add 2 to align the IP header on 4 bytes,
834          * and add the margin for the tcpiphdr overhead  */
835         if (M_FREEROOM(m) < pkt_len + TCPIPHDR_DELTA + 2) {
836             m_inc(m, pkt_len + TCPIPHDR_DELTA + 2);
837         }
838         m->m_len = pkt_len + TCPIPHDR_DELTA + 2;
839         memcpy(m->m_data + TCPIPHDR_DELTA + 2, pkt, pkt_len);
840 
841         m->m_data += TCPIPHDR_DELTA + 2 + ETH_HLEN;
842         m->m_len -= TCPIPHDR_DELTA + 2 + ETH_HLEN;
843 
844         if (proto == ETH_P_IP) {
845             ip_input(m);
846         } else if (proto == ETH_P_IPV6) {
847             ip6_input(m);
848         }
849         break;
850 
851     case ETH_P_NCSI:
852         ncsi_input(slirp, pkt, pkt_len);
853         break;
854 
855     default:
856         break;
857     }
858 }
859 
860 /* Prepare the IPv4 packet to be sent to the ethernet device. Returns 1 if no
861  * packet should be sent, 0 if the packet must be re-queued, 2 if the packet
862  * is ready to go.
863  */
if_encap4(Slirp * slirp,struct mbuf * ifm,struct ethhdr * eh,uint8_t ethaddr[ETH_ALEN])864 static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
865                      uint8_t ethaddr[ETH_ALEN])
866 {
867     const struct ip *iph = (const struct ip *)ifm->m_data;
868 
869     if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
870         uint8_t arp_req[ETH_HLEN + sizeof(struct slirp_arphdr)];
871         struct ethhdr *reh = (struct ethhdr *)arp_req;
872         struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_req + ETH_HLEN);
873 
874         if (!ifm->resolution_requested) {
875             /* If the client addr is not known, send an ARP request */
876             memset(reh->h_dest, 0xff, ETH_ALEN);
877             memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
878             memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
879             reh->h_proto = htons(ETH_P_ARP);
880             rah->ar_hrd = htons(1);
881             rah->ar_pro = htons(ETH_P_IP);
882             rah->ar_hln = ETH_ALEN;
883             rah->ar_pln = 4;
884             rah->ar_op = htons(ARPOP_REQUEST);
885 
886             /* source hw addr */
887             memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
888             memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
889 
890             /* source IP */
891             rah->ar_sip = slirp->vhost_addr.s_addr;
892 
893             /* target hw addr (none) */
894             memset(rah->ar_tha, 0, ETH_ALEN);
895 
896             /* target IP */
897             rah->ar_tip = iph->ip_dst.s_addr;
898             slirp->client_ipaddr = iph->ip_dst;
899             slirp_send_packet_all(slirp, arp_req, sizeof(arp_req));
900             ifm->resolution_requested = true;
901 
902             /* Expire request and drop outgoing packet after 1 second */
903             ifm->expiration_date =
904                 slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
905         }
906         return 0;
907     } else {
908         memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
909         /* XXX: not correct */
910         memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
911         eh->h_proto = htons(ETH_P_IP);
912 
913         /* Send this */
914         return 2;
915     }
916 }
917 
918 /* Prepare the IPv6 packet to be sent to the ethernet device. Returns 1 if no
919  * packet should be sent, 0 if the packet must be re-queued, 2 if the packet
920  * is ready to go.
921  */
if_encap6(Slirp * slirp,struct mbuf * ifm,struct ethhdr * eh,uint8_t ethaddr[ETH_ALEN])922 static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
923                      uint8_t ethaddr[ETH_ALEN])
924 {
925     const struct ip6 *ip6h = mtod(ifm, const struct ip6 *);
926     if (!ndp_table_search(slirp, ip6h->ip_dst, ethaddr)) {
927         if (!ifm->resolution_requested) {
928             ndp_send_ns(slirp, ip6h->ip_dst);
929             ifm->resolution_requested = true;
930             ifm->expiration_date =
931                 slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
932         }
933         return 0;
934     } else {
935         eh->h_proto = htons(ETH_P_IPV6);
936         in6_compute_ethaddr(ip6h->ip_src, eh->h_source);
937 
938         /* Send this */
939         return 2;
940     }
941 }
942 
943 /* Output the IP packet to the ethernet device. Returns 0 if the packet must be
944  * re-queued.
945  */
if_encap(Slirp * slirp,struct mbuf * ifm)946 int if_encap(Slirp *slirp, struct mbuf *ifm)
947 {
948     uint8_t buf[IF_MTU_MAX + 100];
949     struct ethhdr *eh = (struct ethhdr *)buf;
950     uint8_t ethaddr[ETH_ALEN];
951     const struct ip *iph = (const struct ip *)ifm->m_data;
952     int ret;
953 
954     if (ifm->m_len + ETH_HLEN > sizeof(buf)) {
955         return 1;
956     }
957 
958     switch (iph->ip_v) {
959     case IPVERSION:
960         ret = if_encap4(slirp, ifm, eh, ethaddr);
961         if (ret < 2) {
962             return ret;
963         }
964         break;
965 
966     case IP6VERSION:
967         ret = if_encap6(slirp, ifm, eh, ethaddr);
968         if (ret < 2) {
969             return ret;
970         }
971         break;
972 
973     default:
974         g_assert_not_reached();
975     }
976 
977     memcpy(eh->h_dest, ethaddr, ETH_ALEN);
978     DEBUG_ARG("src = %02x:%02x:%02x:%02x:%02x:%02x", eh->h_source[0],
979               eh->h_source[1], eh->h_source[2], eh->h_source[3],
980               eh->h_source[4], eh->h_source[5]);
981     DEBUG_ARG("dst = %02x:%02x:%02x:%02x:%02x:%02x", eh->h_dest[0],
982               eh->h_dest[1], eh->h_dest[2], eh->h_dest[3], eh->h_dest[4],
983               eh->h_dest[5]);
984     memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
985     slirp_send_packet_all(slirp, buf, ifm->m_len + ETH_HLEN);
986     return 1;
987 }
988 
989 /* Drop host forwarding rule, return 0 if found. */
990 /* TODO: IPv6 */
slirp_remove_hostfwd(Slirp * slirp,int is_udp,struct in_addr host_addr,int host_port)991 int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
992                          int host_port)
993 {
994     struct socket *so;
995     struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
996     struct sockaddr_in addr;
997     int port = htons(host_port);
998     socklen_t addr_len;
999 
1000     for (so = head->so_next; so != head; so = so->so_next) {
1001         addr_len = sizeof(addr);
1002         if ((so->so_state & SS_HOSTFWD) &&
1003             getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
1004             addr.sin_addr.s_addr == host_addr.s_addr && addr.sin_port == port) {
1005             so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
1006             closesocket(so->s);
1007             sofree(so);
1008             return 0;
1009         }
1010     }
1011 
1012     return -1;
1013 }
1014 
1015 /* TODO: IPv6 */
slirp_add_hostfwd(Slirp * slirp,int is_udp,struct in_addr host_addr,int host_port,struct in_addr guest_addr,int guest_port)1016 int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
1017                       int host_port, struct in_addr guest_addr, int guest_port)
1018 {
1019     if (!guest_addr.s_addr) {
1020         guest_addr = slirp->vdhcp_startaddr;
1021     }
1022     if (is_udp) {
1023         if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
1024                         guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
1025             return -1;
1026     } else {
1027         if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
1028                         guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
1029             return -1;
1030     }
1031     return 0;
1032 }
1033 
1034 /* TODO: IPv6 */
check_guestfwd(Slirp * slirp,struct in_addr * guest_addr,int guest_port)1035 static bool check_guestfwd(Slirp *slirp, struct in_addr *guest_addr,
1036                            int guest_port)
1037 {
1038     struct gfwd_list *tmp_ptr;
1039 
1040     if (!guest_addr->s_addr) {
1041         guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
1042                              (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
1043     }
1044     if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
1045             slirp->vnetwork_addr.s_addr ||
1046         guest_addr->s_addr == slirp->vhost_addr.s_addr ||
1047         guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
1048         return false;
1049     }
1050 
1051     /* check if the port is "bound" */
1052     for (tmp_ptr = slirp->guestfwd_list; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
1053         if (guest_port == tmp_ptr->ex_fport &&
1054             guest_addr->s_addr == tmp_ptr->ex_addr.s_addr)
1055             return false;
1056     }
1057 
1058     return true;
1059 }
1060 
slirp_add_exec(Slirp * slirp,const char * cmdline,struct in_addr * guest_addr,int guest_port)1061 int slirp_add_exec(Slirp *slirp, const char *cmdline,
1062                    struct in_addr *guest_addr, int guest_port)
1063 {
1064     if (!check_guestfwd(slirp, guest_addr, guest_port)) {
1065         return -1;
1066     }
1067 
1068     add_exec(&slirp->guestfwd_list, cmdline, *guest_addr, htons(guest_port));
1069     return 0;
1070 }
1071 
slirp_add_unix(Slirp * slirp,const char * unixsock,struct in_addr * guest_addr,int guest_port)1072 int slirp_add_unix(Slirp *slirp, const char *unixsock,
1073                    struct in_addr *guest_addr, int guest_port)
1074 {
1075 #ifdef G_OS_UNIX
1076     if (!check_guestfwd(slirp, guest_addr, guest_port)) {
1077         return -1;
1078     }
1079 
1080     add_unix(&slirp->guestfwd_list, unixsock, *guest_addr, htons(guest_port));
1081     return 0;
1082 #else
1083     g_warn_if_reached();
1084     return -1;
1085 #endif
1086 }
1087 
slirp_add_guestfwd(Slirp * slirp,SlirpWriteCb write_cb,void * opaque,struct in_addr * guest_addr,int guest_port)1088 int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
1089                        struct in_addr *guest_addr, int guest_port)
1090 {
1091     if (!check_guestfwd(slirp, guest_addr, guest_port)) {
1092         return -1;
1093     }
1094 
1095     add_guestfwd(&slirp->guestfwd_list, write_cb, opaque, *guest_addr,
1096                  htons(guest_port));
1097     return 0;
1098 }
1099 
slirp_remove_guestfwd(Slirp * slirp,struct in_addr guest_addr,int guest_port)1100 int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr,
1101                           int guest_port)
1102 {
1103     return remove_guestfwd(&slirp->guestfwd_list, guest_addr,
1104                            htons(guest_port));
1105 }
1106 
slirp_send(struct socket * so,const void * buf,size_t len,int flags)1107 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
1108 {
1109     if (so->s == -1 && so->guestfwd) {
1110         /* XXX this blocks entire thread. Rewrite to use
1111          * qemu_chr_fe_write and background I/O callbacks */
1112         so->guestfwd->write_cb(buf, len, so->guestfwd->opaque);
1113         return len;
1114     }
1115 
1116     if (so->s == -1) {
1117         /*
1118          * This should in theory not happen but it is hard to be
1119          * sure because some code paths will end up with so->s == -1
1120          * on a failure but don't dispose of the struct socket.
1121          * Check specifically, so we don't pass -1 to send().
1122          */
1123         errno = EBADF;
1124         return -1;
1125     }
1126 
1127     return send(so->s, buf, len, flags);
1128 }
1129 
slirp_find_ctl_socket(Slirp * slirp,struct in_addr guest_addr,int guest_port)1130 struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr,
1131                                      int guest_port)
1132 {
1133     struct socket *so;
1134 
1135     /* TODO: IPv6 */
1136     for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
1137         if (so->so_faddr.s_addr == guest_addr.s_addr &&
1138             htons(so->so_fport) == guest_port) {
1139             return so;
1140         }
1141     }
1142     return NULL;
1143 }
1144 
slirp_socket_can_recv(Slirp * slirp,struct in_addr guest_addr,int guest_port)1145 size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
1146                              int guest_port)
1147 {
1148     struct iovec iov[2];
1149     struct socket *so;
1150 
1151     so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
1152 
1153     if (!so || so->so_state & SS_NOFDREF) {
1154         return 0;
1155     }
1156 
1157     if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen / 2)) {
1158         return 0;
1159     }
1160 
1161     return sopreprbuf(so, iov, NULL);
1162 }
1163 
slirp_socket_recv(Slirp * slirp,struct in_addr guest_addr,int guest_port,const uint8_t * buf,int size)1164 void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
1165                        const uint8_t *buf, int size)
1166 {
1167     int ret;
1168     struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
1169 
1170     if (!so)
1171         return;
1172 
1173     ret = soreadbuf(so, (const char *)buf, size);
1174 
1175     if (ret > 0)
1176         tcp_output(sototcpcb(so));
1177 }
1178 
slirp_send_packet_all(Slirp * slirp,const void * buf,size_t len)1179 void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len)
1180 {
1181     ssize_t ret = slirp->cb->send_packet(buf, len, slirp->opaque);
1182 
1183     if (ret < 0) {
1184         g_critical("Failed to send packet, ret: %ld", (long)ret);
1185     } else if (ret < len) {
1186         DEBUG_ERROR("send_packet() didn't send all data: %ld < %lu", (long)ret,
1187                     (unsigned long)len);
1188     }
1189 }
1190