xref: /openbmc/qemu/net/slirp.c (revision 5f69e42d)
1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "qemu/log.h"
27 #include "net/slirp.h"
28 
29 
30 #if defined(CONFIG_SMBD_COMMAND)
31 #include <pwd.h>
32 #include <sys/wait.h>
33 #endif
34 #include "net/eth.h"
35 #include "net/net.h"
36 #include "clients.h"
37 #include "hub.h"
38 #include "monitor/monitor.h"
39 #include "qemu/error-report.h"
40 #include "qemu/sockets.h"
41 #include <libslirp.h>
42 #include "chardev/char-fe.h"
43 #include "sysemu/sysemu.h"
44 #include "qemu/cutils.h"
45 #include "qapi/error.h"
46 #include "qapi/qmp/qdict.h"
47 #include "util.h"
48 #include "migration/register.h"
49 #include "migration/vmstate.h"
50 #include "migration/qemu-file-types.h"
51 
52 static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
53 {
54     const char *p, *p1;
55     int len;
56     p = *pp;
57     p1 = strchr(p, sep);
58     if (!p1)
59         return -1;
60     len = p1 - p;
61     p1++;
62     if (buf_size > 0) {
63         if (len > buf_size - 1)
64             len = buf_size - 1;
65         memcpy(buf, p, len);
66         buf[len] = '\0';
67     }
68     *pp = p1;
69     return 0;
70 }
71 
72 /* slirp network adapter */
73 
74 #define SLIRP_CFG_HOSTFWD 1
75 
76 struct slirp_config_str {
77     struct slirp_config_str *next;
78     int flags;
79     char str[1024];
80 };
81 
82 struct GuestFwd {
83     CharBackend hd;
84     struct in_addr server;
85     int port;
86     Slirp *slirp;
87 };
88 
89 typedef struct SlirpState {
90     NetClientState nc;
91     QTAILQ_ENTRY(SlirpState) entry;
92     Slirp *slirp;
93     Notifier poll_notifier;
94     Notifier exit_notifier;
95 #if defined(CONFIG_SMBD_COMMAND)
96     gchar *smb_dir;
97 #endif
98     GSList *fwd;
99 } SlirpState;
100 
101 static struct slirp_config_str *slirp_configs;
102 static QTAILQ_HEAD(, SlirpState) slirp_stacks =
103     QTAILQ_HEAD_INITIALIZER(slirp_stacks);
104 
105 static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp);
106 static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp);
107 
108 #if defined(CONFIG_SMBD_COMMAND)
109 static int slirp_smb(SlirpState *s, const char *exported_dir,
110                      struct in_addr vserver_addr, Error **errp);
111 static void slirp_smb_cleanup(SlirpState *s);
112 #else
113 static inline void slirp_smb_cleanup(SlirpState *s) { }
114 #endif
115 
116 static ssize_t net_slirp_send_packet(const void *pkt, size_t pkt_len,
117                                      void *opaque)
118 {
119     SlirpState *s = opaque;
120     uint8_t min_pkt[ETH_ZLEN];
121     size_t min_pktsz = sizeof(min_pkt);
122 
123     if (net_peer_needs_padding(&s->nc)) {
124         if (eth_pad_short_frame(min_pkt, &min_pktsz, pkt, pkt_len)) {
125             pkt = min_pkt;
126             pkt_len = min_pktsz;
127         }
128     }
129 
130     return qemu_send_packet(&s->nc, pkt, pkt_len);
131 }
132 
133 static ssize_t net_slirp_receive(NetClientState *nc, const uint8_t *buf, size_t size)
134 {
135     SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
136 
137     slirp_input(s->slirp, buf, size);
138 
139     return size;
140 }
141 
142 static void slirp_smb_exit(Notifier *n, void *data)
143 {
144     SlirpState *s = container_of(n, SlirpState, exit_notifier);
145     slirp_smb_cleanup(s);
146 }
147 
148 static void slirp_free_fwd(gpointer data)
149 {
150     struct GuestFwd *fwd = data;
151 
152     qemu_chr_fe_deinit(&fwd->hd, true);
153     g_free(data);
154 }
155 
156 static void net_slirp_cleanup(NetClientState *nc)
157 {
158     SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
159 
160     g_slist_free_full(s->fwd, slirp_free_fwd);
161     main_loop_poll_remove_notifier(&s->poll_notifier);
162     unregister_savevm(NULL, "slirp", s->slirp);
163     slirp_cleanup(s->slirp);
164     if (s->exit_notifier.notify) {
165         qemu_remove_exit_notifier(&s->exit_notifier);
166     }
167     slirp_smb_cleanup(s);
168     QTAILQ_REMOVE(&slirp_stacks, s, entry);
169 }
170 
171 static NetClientInfo net_slirp_info = {
172     .type = NET_CLIENT_DRIVER_USER,
173     .size = sizeof(SlirpState),
174     .receive = net_slirp_receive,
175     .cleanup = net_slirp_cleanup,
176 };
177 
178 static void net_slirp_guest_error(const char *msg, void *opaque)
179 {
180     qemu_log_mask(LOG_GUEST_ERROR, "%s", msg);
181 }
182 
183 static int64_t net_slirp_clock_get_ns(void *opaque)
184 {
185     return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
186 }
187 
188 typedef struct SlirpTimer SlirpTimer;
189 struct SlirpTimer {
190     QEMUTimer timer;
191 #if SLIRP_CHECK_VERSION(4,7,0)
192     Slirp *slirp;
193     SlirpTimerId id;
194     void *cb_opaque;
195 #endif
196 };
197 
198 #if SLIRP_CHECK_VERSION(4,7,0)
199 static void net_slirp_init_completed(Slirp *slirp, void *opaque)
200 {
201     SlirpState *s = opaque;
202     s->slirp = slirp;
203 }
204 
205 static void net_slirp_timer_cb(void *opaque)
206 {
207     SlirpTimer *t = opaque;
208     slirp_handle_timer(t->slirp, t->id, t->cb_opaque);
209 }
210 
211 static void *net_slirp_timer_new_opaque(SlirpTimerId id,
212                                         void *cb_opaque, void *opaque)
213 {
214     SlirpState *s = opaque;
215     SlirpTimer *t = g_new(SlirpTimer, 1);
216     t->slirp = s->slirp;
217     t->id = id;
218     t->cb_opaque = cb_opaque;
219     timer_init_full(&t->timer, NULL, QEMU_CLOCK_VIRTUAL,
220                     SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
221                     net_slirp_timer_cb, t);
222     return t;
223 }
224 #else
225 static void *net_slirp_timer_new(SlirpTimerCb cb,
226                                  void *cb_opaque, void *opaque)
227 {
228     SlirpTimer *t = g_new(SlirpTimer, 1);
229     timer_init_full(&t->timer, NULL, QEMU_CLOCK_VIRTUAL,
230                     SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
231                     cb, cb_opaque);
232     return t;
233 }
234 #endif
235 
236 static void net_slirp_timer_free(void *timer, void *opaque)
237 {
238     SlirpTimer *t = timer;
239     timer_del(&t->timer);
240     g_free(t);
241 }
242 
243 static void net_slirp_timer_mod(void *timer, int64_t expire_timer,
244                                 void *opaque)
245 {
246     SlirpTimer *t = timer;
247     timer_mod(&t->timer, expire_timer);
248 }
249 
250 static void net_slirp_register_poll_fd(int fd, void *opaque)
251 {
252 #ifdef WIN32
253     AioContext *ctxt = qemu_get_aio_context();
254 
255     if (WSAEventSelect(fd, event_notifier_get_handle(&ctxt->notifier),
256                        FD_READ | FD_ACCEPT | FD_CLOSE |
257                        FD_CONNECT | FD_WRITE | FD_OOB) != 0) {
258         error_setg_win32(&error_warn, WSAGetLastError(), "failed to WSAEventSelect()");
259     }
260 #endif
261 }
262 
263 static void net_slirp_unregister_poll_fd(int fd, void *opaque)
264 {
265 #ifdef WIN32
266     if (WSAEventSelect(fd, NULL, 0) != 0) {
267         error_setg_win32(&error_warn, WSAGetLastError(), "failed to WSAEventSelect()");
268     }
269 #endif
270 }
271 
272 static void net_slirp_notify(void *opaque)
273 {
274     qemu_notify_event();
275 }
276 
277 static const SlirpCb slirp_cb = {
278     .send_packet = net_slirp_send_packet,
279     .guest_error = net_slirp_guest_error,
280     .clock_get_ns = net_slirp_clock_get_ns,
281 #if SLIRP_CHECK_VERSION(4,7,0)
282     .init_completed = net_slirp_init_completed,
283     .timer_new_opaque = net_slirp_timer_new_opaque,
284 #else
285     .timer_new = net_slirp_timer_new,
286 #endif
287     .timer_free = net_slirp_timer_free,
288     .timer_mod = net_slirp_timer_mod,
289     .register_poll_fd = net_slirp_register_poll_fd,
290     .unregister_poll_fd = net_slirp_unregister_poll_fd,
291     .notify = net_slirp_notify,
292 };
293 
294 static int slirp_poll_to_gio(int events)
295 {
296     int ret = 0;
297 
298     if (events & SLIRP_POLL_IN) {
299         ret |= G_IO_IN;
300     }
301     if (events & SLIRP_POLL_OUT) {
302         ret |= G_IO_OUT;
303     }
304     if (events & SLIRP_POLL_PRI) {
305         ret |= G_IO_PRI;
306     }
307     if (events & SLIRP_POLL_ERR) {
308         ret |= G_IO_ERR;
309     }
310     if (events & SLIRP_POLL_HUP) {
311         ret |= G_IO_HUP;
312     }
313 
314     return ret;
315 }
316 
317 static int net_slirp_add_poll(int fd, int events, void *opaque)
318 {
319     GArray *pollfds = opaque;
320     GPollFD pfd = {
321         .fd = fd,
322         .events = slirp_poll_to_gio(events),
323     };
324     int idx = pollfds->len;
325     g_array_append_val(pollfds, pfd);
326     return idx;
327 }
328 
329 static int slirp_gio_to_poll(int events)
330 {
331     int ret = 0;
332 
333     if (events & G_IO_IN) {
334         ret |= SLIRP_POLL_IN;
335     }
336     if (events & G_IO_OUT) {
337         ret |= SLIRP_POLL_OUT;
338     }
339     if (events & G_IO_PRI) {
340         ret |= SLIRP_POLL_PRI;
341     }
342     if (events & G_IO_ERR) {
343         ret |= SLIRP_POLL_ERR;
344     }
345     if (events & G_IO_HUP) {
346         ret |= SLIRP_POLL_HUP;
347     }
348 
349     return ret;
350 }
351 
352 static int net_slirp_get_revents(int idx, void *opaque)
353 {
354     GArray *pollfds = opaque;
355 
356     return slirp_gio_to_poll(g_array_index(pollfds, GPollFD, idx).revents);
357 }
358 
359 static void net_slirp_poll_notify(Notifier *notifier, void *data)
360 {
361     MainLoopPoll *poll = data;
362     SlirpState *s = container_of(notifier, SlirpState, poll_notifier);
363 
364     switch (poll->state) {
365     case MAIN_LOOP_POLL_FILL:
366         slirp_pollfds_fill(s->slirp, &poll->timeout,
367                            net_slirp_add_poll, poll->pollfds);
368         break;
369     case MAIN_LOOP_POLL_OK:
370     case MAIN_LOOP_POLL_ERR:
371         slirp_pollfds_poll(s->slirp, poll->state == MAIN_LOOP_POLL_ERR,
372                            net_slirp_get_revents, poll->pollfds);
373         break;
374     default:
375         g_assert_not_reached();
376     }
377 }
378 
379 static ssize_t
380 net_slirp_stream_read(void *buf, size_t size, void *opaque)
381 {
382     QEMUFile *f = opaque;
383 
384     return qemu_get_buffer(f, buf, size);
385 }
386 
387 static ssize_t
388 net_slirp_stream_write(const void *buf, size_t size, void *opaque)
389 {
390     QEMUFile *f = opaque;
391 
392     qemu_put_buffer(f, buf, size);
393     if (qemu_file_get_error(f)) {
394         return -1;
395     }
396 
397     return size;
398 }
399 
400 static int net_slirp_state_load(QEMUFile *f, void *opaque, int version_id)
401 {
402     Slirp *slirp = opaque;
403 
404     return slirp_state_load(slirp, version_id, net_slirp_stream_read, f);
405 }
406 
407 static void net_slirp_state_save(QEMUFile *f, void *opaque)
408 {
409     Slirp *slirp = opaque;
410 
411     slirp_state_save(slirp, net_slirp_stream_write, f);
412 }
413 
414 static SaveVMHandlers savevm_slirp_state = {
415     .save_state = net_slirp_state_save,
416     .load_state = net_slirp_state_load,
417 };
418 
419 static int net_slirp_init(NetClientState *peer, const char *model,
420                           const char *name, int restricted,
421                           bool ipv4, const char *vnetwork, const char *vhost,
422                           bool ipv6, const char *vprefix6, int vprefix6_len,
423                           const char *vhost6,
424                           const char *vhostname, const char *tftp_export,
425                           const char *bootfile, const char *vdhcp_start,
426                           const char *vnameserver, const char *vnameserver6,
427                           const char *smb_export, const char *vsmbserver,
428                           const char **dnssearch, const char *vdomainname,
429                           const char *tftp_server_name,
430                           Error **errp)
431 {
432     /* default settings according to historic slirp */
433     struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
434     struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */
435     struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
436     struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
437     struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
438     struct in6_addr ip6_prefix;
439     struct in6_addr ip6_host;
440     struct in6_addr ip6_dns;
441 #if defined(CONFIG_SMBD_COMMAND)
442     struct in_addr smbsrv = { .s_addr = 0 };
443 #endif
444     SlirpConfig cfg = { 0 };
445     NetClientState *nc;
446     SlirpState *s;
447     char buf[20];
448     uint32_t addr;
449     int shift;
450     char *end;
451     struct slirp_config_str *config;
452 
453     if (!ipv4 && (vnetwork || vhost || vnameserver)) {
454         error_setg(errp, "IPv4 disabled but netmask/host/dns provided");
455         return -1;
456     }
457 
458     if (!ipv6 && (vprefix6 || vhost6 || vnameserver6)) {
459         error_setg(errp, "IPv6 disabled but prefix/host6/dns6 provided");
460         return -1;
461     }
462 
463     if (!ipv4 && !ipv6) {
464         /* It doesn't make sense to disable both */
465         error_setg(errp, "IPv4 and IPv6 disabled");
466         return -1;
467     }
468 
469     if (vnetwork) {
470         if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
471             if (!inet_aton(vnetwork, &net)) {
472                 error_setg(errp, "Failed to parse netmask");
473                 return -1;
474             }
475             addr = ntohl(net.s_addr);
476             if (!(addr & 0x80000000)) {
477                 mask.s_addr = htonl(0xff000000); /* class A */
478             } else if ((addr & 0xfff00000) == 0xac100000) {
479                 mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
480             } else if ((addr & 0xc0000000) == 0x80000000) {
481                 mask.s_addr = htonl(0xffff0000); /* class B */
482             } else if ((addr & 0xffff0000) == 0xc0a80000) {
483                 mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
484             } else if ((addr & 0xffff0000) == 0xc6120000) {
485                 mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
486             } else if ((addr & 0xe0000000) == 0xe0000000) {
487                 mask.s_addr = htonl(0xffffff00); /* class C */
488             } else {
489                 mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
490             }
491         } else {
492             if (!inet_aton(buf, &net)) {
493                 error_setg(errp, "Failed to parse netmask");
494                 return -1;
495             }
496             shift = strtol(vnetwork, &end, 10);
497             if (*end != '\0') {
498                 if (!inet_aton(vnetwork, &mask)) {
499                     error_setg(errp,
500                                "Failed to parse netmask (trailing chars)");
501                     return -1;
502                 }
503             } else if (shift < 4 || shift > 32) {
504                 error_setg(errp,
505                            "Invalid netmask provided (must be in range 4-32)");
506                 return -1;
507             } else {
508                 mask.s_addr = htonl(0xffffffff << (32 - shift));
509             }
510         }
511         net.s_addr &= mask.s_addr;
512         host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
513         dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
514         dns.s_addr  = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
515     }
516 
517     if (vhost && !inet_aton(vhost, &host)) {
518         error_setg(errp, "Failed to parse host");
519         return -1;
520     }
521     if ((host.s_addr & mask.s_addr) != net.s_addr) {
522         error_setg(errp, "Host doesn't belong to network");
523         return -1;
524     }
525 
526     if (vnameserver && !inet_aton(vnameserver, &dns)) {
527         error_setg(errp, "Failed to parse DNS");
528         return -1;
529     }
530     if (restricted && (dns.s_addr & mask.s_addr) != net.s_addr) {
531         error_setg(errp, "DNS doesn't belong to network");
532         return -1;
533     }
534     if (dns.s_addr == host.s_addr) {
535         error_setg(errp, "DNS must be different from host");
536         return -1;
537     }
538 
539     if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
540         error_setg(errp, "Failed to parse DHCP start address");
541         return -1;
542     }
543     if ((dhcp.s_addr & mask.s_addr) != net.s_addr) {
544         error_setg(errp, "DHCP doesn't belong to network");
545         return -1;
546     }
547     if (dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
548         error_setg(errp, "DHCP must be different from host and DNS");
549         return -1;
550     }
551 
552 #if defined(CONFIG_SMBD_COMMAND)
553     if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
554         error_setg(errp, "Failed to parse SMB address");
555         return -1;
556     }
557 #endif
558 
559     if (!vprefix6) {
560         vprefix6 = "fec0::";
561     }
562     if (!inet_pton(AF_INET6, vprefix6, &ip6_prefix)) {
563         error_setg(errp, "Failed to parse IPv6 prefix");
564         return -1;
565     }
566 
567     if (!vprefix6_len) {
568         vprefix6_len = 64;
569     }
570     if (vprefix6_len < 0 || vprefix6_len > 126) {
571         error_setg(errp,
572                    "Invalid IPv6 prefix provided "
573                    "(IPv6 prefix length must be between 0 and 126)");
574         return -1;
575     }
576 
577     if (vhost6) {
578         if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
579             error_setg(errp, "Failed to parse IPv6 host");
580             return -1;
581         }
582         if (!in6_equal_net(&ip6_prefix, &ip6_host, vprefix6_len)) {
583             error_setg(errp, "IPv6 Host doesn't belong to network");
584             return -1;
585         }
586     } else {
587         ip6_host = ip6_prefix;
588         ip6_host.s6_addr[15] |= 2;
589     }
590 
591     if (vnameserver6) {
592         if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
593             error_setg(errp, "Failed to parse IPv6 DNS");
594             return -1;
595         }
596         if (restricted && !in6_equal_net(&ip6_prefix, &ip6_dns, vprefix6_len)) {
597             error_setg(errp, "IPv6 DNS doesn't belong to network");
598             return -1;
599         }
600     } else {
601         ip6_dns = ip6_prefix;
602         ip6_dns.s6_addr[15] |= 3;
603     }
604 
605     if (vdomainname && !*vdomainname) {
606         error_setg(errp, "'domainname' parameter cannot be empty");
607         return -1;
608     }
609 
610     if (vdomainname && strlen(vdomainname) > 255) {
611         error_setg(errp, "'domainname' parameter cannot exceed 255 bytes");
612         return -1;
613     }
614 
615     if (vhostname && strlen(vhostname) > 255) {
616         error_setg(errp, "'vhostname' parameter cannot exceed 255 bytes");
617         return -1;
618     }
619 
620     if (tftp_server_name && strlen(tftp_server_name) > 255) {
621         error_setg(errp, "'tftp-server-name' parameter cannot exceed 255 bytes");
622         return -1;
623     }
624 
625     nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
626 
627     qemu_set_info_str(nc, "net=%s,restrict=%s", inet_ntoa(net),
628                       restricted ? "on" : "off");
629 
630     s = DO_UPCAST(SlirpState, nc, nc);
631 
632     cfg.version = SLIRP_CHECK_VERSION(4,7,0) ? 4 : 1;
633     cfg.restricted = restricted;
634     cfg.in_enabled = ipv4;
635     cfg.vnetwork = net;
636     cfg.vnetmask = mask;
637     cfg.vhost = host;
638     cfg.in6_enabled = ipv6;
639     cfg.vprefix_addr6 = ip6_prefix;
640     cfg.vprefix_len = vprefix6_len;
641     cfg.vhost6 = ip6_host;
642     cfg.vhostname = vhostname;
643     cfg.tftp_server_name = tftp_server_name;
644     cfg.tftp_path = tftp_export;
645     cfg.bootfile = bootfile;
646     cfg.vdhcp_start = dhcp;
647     cfg.vnameserver = dns;
648     cfg.vnameserver6 = ip6_dns;
649     cfg.vdnssearch = dnssearch;
650     cfg.vdomainname = vdomainname;
651     s->slirp = slirp_new(&cfg, &slirp_cb, s);
652     QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
653 
654     /*
655      * Make sure the current bitstream version of slirp is 4, to avoid
656      * QEMU migration incompatibilities, if upstream slirp bumped the
657      * version.
658      *
659      * FIXME: use bitfields of features? teach libslirp to save with
660      * specific version?
661      */
662     g_assert(slirp_state_version() == 4);
663     register_savevm_live("slirp", VMSTATE_INSTANCE_ID_ANY,
664                          slirp_state_version(), &savevm_slirp_state, s->slirp);
665 
666     s->poll_notifier.notify = net_slirp_poll_notify;
667     main_loop_poll_add_notifier(&s->poll_notifier);
668 
669     for (config = slirp_configs; config; config = config->next) {
670         if (config->flags & SLIRP_CFG_HOSTFWD) {
671             if (slirp_hostfwd(s, config->str, errp) < 0) {
672                 goto error;
673             }
674         } else {
675             if (slirp_guestfwd(s, config->str, errp) < 0) {
676                 goto error;
677             }
678         }
679     }
680 #if defined(CONFIG_SMBD_COMMAND)
681     if (smb_export) {
682         if (slirp_smb(s, smb_export, smbsrv, errp) < 0) {
683             goto error;
684         }
685     }
686 #endif
687 
688     s->exit_notifier.notify = slirp_smb_exit;
689     qemu_add_exit_notifier(&s->exit_notifier);
690     return 0;
691 
692 error:
693     qemu_del_net_client(nc);
694     return -1;
695 }
696 
697 static SlirpState *slirp_lookup(Monitor *mon, const char *id)
698 {
699     if (id) {
700         NetClientState *nc = qemu_find_netdev(id);
701         if (!nc) {
702             monitor_printf(mon, "unrecognized netdev id '%s'\n", id);
703             return NULL;
704         }
705         if (strcmp(nc->model, "user")) {
706             monitor_printf(mon, "invalid device specified\n");
707             return NULL;
708         }
709         return DO_UPCAST(SlirpState, nc, nc);
710     } else {
711         if (QTAILQ_EMPTY(&slirp_stacks)) {
712             monitor_printf(mon, "user mode network stack not in use\n");
713             return NULL;
714         }
715         return QTAILQ_FIRST(&slirp_stacks);
716     }
717 }
718 
719 void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
720 {
721     struct sockaddr_in host_addr = {
722         .sin_family = AF_INET,
723         .sin_addr = {
724             .s_addr = INADDR_ANY,
725         },
726     };
727     int host_port;
728     char buf[256];
729     const char *src_str, *p;
730     SlirpState *s;
731     int is_udp = 0;
732     int err;
733     const char *arg1 = qdict_get_str(qdict, "arg1");
734     const char *arg2 = qdict_get_try_str(qdict, "arg2");
735 
736     if (arg2) {
737         s = slirp_lookup(mon, arg1);
738         src_str = arg2;
739     } else {
740         s = slirp_lookup(mon, NULL);
741         src_str = arg1;
742     }
743     if (!s) {
744         return;
745     }
746 
747     p = src_str;
748     if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
749         goto fail_syntax;
750     }
751 
752     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
753         is_udp = 0;
754     } else if (!strcmp(buf, "udp")) {
755         is_udp = 1;
756     } else {
757         goto fail_syntax;
758     }
759 
760     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
761         goto fail_syntax;
762     }
763     if (buf[0] != '\0' && !inet_aton(buf, &host_addr.sin_addr)) {
764         goto fail_syntax;
765     }
766 
767     if (qemu_strtoi(p, NULL, 10, &host_port)) {
768         goto fail_syntax;
769     }
770     host_addr.sin_port = htons(host_port);
771 
772 #if SLIRP_CHECK_VERSION(4, 5, 0)
773     err = slirp_remove_hostxfwd(s->slirp, (struct sockaddr *) &host_addr,
774             sizeof(host_addr), is_udp ? SLIRP_HOSTFWD_UDP : 0);
775 #else
776     err = slirp_remove_hostfwd(s->slirp, is_udp, host_addr.sin_addr, host_port);
777 #endif
778 
779     monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
780                    err ? "not found" : "removed");
781     return;
782 
783  fail_syntax:
784     monitor_printf(mon, "invalid format\n");
785 }
786 
787 static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
788 {
789     struct sockaddr_in host_addr = {
790         .sin_family = AF_INET,
791         .sin_addr = {
792             .s_addr = INADDR_ANY,
793         },
794     };
795     struct sockaddr_in guest_addr = {
796         .sin_family = AF_INET,
797         .sin_addr = {
798             .s_addr = 0,
799         },
800     };
801     int err;
802     int host_port, guest_port;
803     const char *p;
804     char buf[256];
805     int is_udp;
806     const char *end;
807     const char *fail_reason = "Unknown reason";
808 
809     p = redir_str;
810     if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
811         fail_reason = "No : separators";
812         goto fail_syntax;
813     }
814     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
815         is_udp = 0;
816     } else if (!strcmp(buf, "udp")) {
817         is_udp = 1;
818     } else {
819         fail_reason = "Bad protocol name";
820         goto fail_syntax;
821     }
822 
823     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
824         fail_reason = "Missing : separator";
825         goto fail_syntax;
826     }
827     if (buf[0] != '\0' && !inet_aton(buf, &host_addr.sin_addr)) {
828         fail_reason = "Bad host address";
829         goto fail_syntax;
830     }
831 
832     if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
833         fail_reason = "Bad host port separator";
834         goto fail_syntax;
835     }
836     err = qemu_strtoi(buf, &end, 0, &host_port);
837     if (err || host_port < 0 || host_port > 65535) {
838         fail_reason = "Bad host port";
839         goto fail_syntax;
840     }
841     host_addr.sin_port = htons(host_port);
842 
843     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
844         fail_reason = "Missing guest address";
845         goto fail_syntax;
846     }
847     if (buf[0] != '\0' && !inet_aton(buf, &guest_addr.sin_addr)) {
848         fail_reason = "Bad guest address";
849         goto fail_syntax;
850     }
851 
852     err = qemu_strtoi(p, &end, 0, &guest_port);
853     if (err || guest_port < 1 || guest_port > 65535) {
854         fail_reason = "Bad guest port";
855         goto fail_syntax;
856     }
857     guest_addr.sin_port = htons(guest_port);
858 
859 #if SLIRP_CHECK_VERSION(4, 5, 0)
860     err = slirp_add_hostxfwd(s->slirp,
861             (struct sockaddr *) &host_addr, sizeof(host_addr),
862             (struct sockaddr *) &guest_addr, sizeof(guest_addr),
863             is_udp ? SLIRP_HOSTFWD_UDP : 0);
864 #else
865     err = slirp_add_hostfwd(s->slirp, is_udp,
866             host_addr.sin_addr, host_port,
867             guest_addr.sin_addr, guest_port);
868 #endif
869 
870     if (err < 0) {
871         error_setg(errp, "Could not set up host forwarding rule '%s'",
872                    redir_str);
873         return -1;
874     }
875     return 0;
876 
877  fail_syntax:
878     error_setg(errp, "Invalid host forwarding rule '%s' (%s)", redir_str,
879                fail_reason);
880     return -1;
881 }
882 
883 void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
884 {
885     const char *redir_str;
886     SlirpState *s;
887     const char *arg1 = qdict_get_str(qdict, "arg1");
888     const char *arg2 = qdict_get_try_str(qdict, "arg2");
889 
890     if (arg2) {
891         s = slirp_lookup(mon, arg1);
892         redir_str = arg2;
893     } else {
894         s = slirp_lookup(mon, NULL);
895         redir_str = arg1;
896     }
897     if (s) {
898         Error *err = NULL;
899         if (slirp_hostfwd(s, redir_str, &err) < 0) {
900             error_report_err(err);
901         }
902     }
903 
904 }
905 
906 #if defined(CONFIG_SMBD_COMMAND)
907 
908 /* automatic user mode samba server configuration */
909 static void slirp_smb_cleanup(SlirpState *s)
910 {
911     int ret;
912 
913     if (s->smb_dir) {
914         gchar *cmd = g_strdup_printf("rm -rf %s", s->smb_dir);
915         ret = system(cmd);
916         if (ret == -1 || !WIFEXITED(ret)) {
917             error_report("'%s' failed.", cmd);
918         } else if (WEXITSTATUS(ret)) {
919             error_report("'%s' failed. Error code: %d",
920                          cmd, WEXITSTATUS(ret));
921         }
922         g_free(cmd);
923         g_free(s->smb_dir);
924         s->smb_dir = NULL;
925     }
926 }
927 
928 static int slirp_smb(SlirpState* s, const char *exported_dir,
929                      struct in_addr vserver_addr, Error **errp)
930 {
931     char *smb_conf;
932     char *smb_cmdline;
933     struct passwd *passwd;
934     FILE *f;
935 
936     passwd = getpwuid(geteuid());
937     if (!passwd) {
938         error_setg(errp, "Failed to retrieve user name");
939         return -1;
940     }
941 
942     if (access(CONFIG_SMBD_COMMAND, F_OK)) {
943         error_setg(errp, "Could not find '%s', please install it",
944                    CONFIG_SMBD_COMMAND);
945         return -1;
946     }
947 
948     if (access(exported_dir, R_OK | X_OK)) {
949         error_setg(errp, "Error accessing shared directory '%s': %s",
950                    exported_dir, strerror(errno));
951         return -1;
952     }
953 
954     s->smb_dir = g_dir_make_tmp("qemu-smb.XXXXXX", NULL);
955     if (!s->smb_dir) {
956         error_setg(errp, "Could not create samba server dir");
957         return -1;
958     }
959     smb_conf = g_strdup_printf("%s/%s", s->smb_dir, "smb.conf");
960 
961     f = fopen(smb_conf, "w");
962     if (!f) {
963         slirp_smb_cleanup(s);
964         error_setg(errp,
965                    "Could not create samba server configuration file '%s'",
966                     smb_conf);
967         g_free(smb_conf);
968         return -1;
969     }
970     fprintf(f,
971             "[global]\n"
972             "private dir=%s\n"
973             "interfaces=127.0.0.1\n"
974             "bind interfaces only=yes\n"
975             "pid directory=%s\n"
976             "lock directory=%s\n"
977             "state directory=%s\n"
978             "cache directory=%s\n"
979             "ncalrpc dir=%s/ncalrpc\n"
980             "log file=%s/log.smbd\n"
981             "smb passwd file=%s/smbpasswd\n"
982             "security = user\n"
983             "map to guest = Bad User\n"
984             "load printers = no\n"
985             "printing = bsd\n"
986             "disable spoolss = yes\n"
987             "usershare max shares = 0\n"
988             "[qemu]\n"
989             "path=%s\n"
990             "read only=no\n"
991             "guest ok=yes\n"
992             "force user=%s\n",
993             s->smb_dir,
994             s->smb_dir,
995             s->smb_dir,
996             s->smb_dir,
997             s->smb_dir,
998             s->smb_dir,
999             s->smb_dir,
1000             s->smb_dir,
1001             exported_dir,
1002             passwd->pw_name
1003             );
1004     fclose(f);
1005 
1006     smb_cmdline = g_strdup_printf("%s -l %s -s %s",
1007              CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
1008     g_free(smb_conf);
1009 
1010     if (slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 139) < 0 ||
1011         slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 445) < 0) {
1012         slirp_smb_cleanup(s);
1013         g_free(smb_cmdline);
1014         error_setg(errp, "Conflicting/invalid smbserver address");
1015         return -1;
1016     }
1017     g_free(smb_cmdline);
1018     return 0;
1019 }
1020 
1021 #endif /* defined(CONFIG_SMBD_COMMAND) */
1022 
1023 static int guestfwd_can_read(void *opaque)
1024 {
1025     struct GuestFwd *fwd = opaque;
1026     return slirp_socket_can_recv(fwd->slirp, fwd->server, fwd->port);
1027 }
1028 
1029 static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
1030 {
1031     struct GuestFwd *fwd = opaque;
1032     slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
1033 }
1034 
1035 static ssize_t guestfwd_write(const void *buf, size_t len, void *chr)
1036 {
1037     return qemu_chr_fe_write_all(chr, buf, len);
1038 }
1039 
1040 static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
1041 {
1042     /* TODO: IPv6 */
1043     struct in_addr server = { .s_addr = 0 };
1044     struct GuestFwd *fwd;
1045     const char *p;
1046     char buf[128];
1047     char *end;
1048     int port;
1049 
1050     p = config_str;
1051     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1052         goto fail_syntax;
1053     }
1054     if (strcmp(buf, "tcp") && buf[0] != '\0') {
1055         goto fail_syntax;
1056     }
1057     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1058         goto fail_syntax;
1059     }
1060     if (buf[0] != '\0' && !inet_aton(buf, &server)) {
1061         goto fail_syntax;
1062     }
1063     if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
1064         goto fail_syntax;
1065     }
1066     port = strtol(buf, &end, 10);
1067     if (*end != '\0' || port < 1 || port > 65535) {
1068         goto fail_syntax;
1069     }
1070 
1071     snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
1072 
1073     if (g_str_has_prefix(p, "cmd:")) {
1074         if (slirp_add_exec(s->slirp, &p[4], &server, port) < 0) {
1075             error_setg(errp, "Conflicting/invalid host:port in guest "
1076                        "forwarding rule '%s'", config_str);
1077             return -1;
1078         }
1079     } else {
1080         Error *err = NULL;
1081         /*
1082          * FIXME: sure we want to support implicit
1083          * muxed monitors here?
1084          */
1085         Chardev *chr = qemu_chr_new_mux_mon(buf, p, NULL);
1086 
1087         if (!chr) {
1088             error_setg(errp, "Could not open guest forwarding device '%s'",
1089                        buf);
1090             return -1;
1091         }
1092 
1093         fwd = g_new(struct GuestFwd, 1);
1094         qemu_chr_fe_init(&fwd->hd, chr, &err);
1095         if (err) {
1096             error_propagate(errp, err);
1097             object_unparent(OBJECT(chr));
1098             g_free(fwd);
1099             return -1;
1100         }
1101 
1102         if (slirp_add_guestfwd(s->slirp, guestfwd_write, &fwd->hd,
1103                                &server, port) < 0) {
1104             error_setg(errp, "Conflicting/invalid host:port in guest "
1105                        "forwarding rule '%s'", config_str);
1106             qemu_chr_fe_deinit(&fwd->hd, true);
1107             g_free(fwd);
1108             return -1;
1109         }
1110         fwd->server = server;
1111         fwd->port = port;
1112         fwd->slirp = s->slirp;
1113 
1114         qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
1115                                  NULL, NULL, fwd, NULL, true);
1116         s->fwd = g_slist_append(s->fwd, fwd);
1117     }
1118     return 0;
1119 
1120  fail_syntax:
1121     error_setg(errp, "Invalid guest forwarding rule '%s'", config_str);
1122     return -1;
1123 }
1124 
1125 void hmp_info_usernet(Monitor *mon, const QDict *qdict)
1126 {
1127     SlirpState *s;
1128 
1129     QTAILQ_FOREACH(s, &slirp_stacks, entry) {
1130         int id;
1131         bool got_hub_id = net_hub_id_for_client(&s->nc, &id) == 0;
1132         char *info = slirp_connection_info(s->slirp);
1133         monitor_printf(mon, "Hub %d (%s):\n%s",
1134                        got_hub_id ? id : -1,
1135                        s->nc.name, info);
1136         g_free(info);
1137     }
1138 }
1139 
1140 static void
1141 net_init_slirp_configs(const StringList *fwd, int flags)
1142 {
1143     while (fwd) {
1144         struct slirp_config_str *config;
1145 
1146         config = g_malloc0(sizeof(*config));
1147         pstrcpy(config->str, sizeof(config->str), fwd->value->str);
1148         config->flags = flags;
1149         config->next = slirp_configs;
1150         slirp_configs = config;
1151 
1152         fwd = fwd->next;
1153     }
1154 }
1155 
1156 static const char **slirp_dnssearch(const StringList *dnsname)
1157 {
1158     const StringList *c = dnsname;
1159     size_t i = 0, num_opts = 0;
1160     const char **ret;
1161 
1162     while (c) {
1163         num_opts++;
1164         c = c->next;
1165     }
1166 
1167     if (num_opts == 0) {
1168         return NULL;
1169     }
1170 
1171     ret = g_malloc((num_opts + 1) * sizeof(*ret));
1172     c = dnsname;
1173     while (c) {
1174         ret[i++] = c->value->str;
1175         c = c->next;
1176     }
1177     ret[i] = NULL;
1178     return ret;
1179 }
1180 
1181 int net_init_slirp(const Netdev *netdev, const char *name,
1182                    NetClientState *peer, Error **errp)
1183 {
1184     struct slirp_config_str *config;
1185     char *vnet;
1186     int ret;
1187     const NetdevUserOptions *user;
1188     const char **dnssearch;
1189     bool ipv4 = true, ipv6 = true;
1190 
1191     assert(netdev->type == NET_CLIENT_DRIVER_USER);
1192     user = &netdev->u.user;
1193 
1194     if ((user->has_ipv6 && user->ipv6 && !user->has_ipv4) ||
1195         (user->has_ipv4 && !user->ipv4)) {
1196         ipv4 = 0;
1197     }
1198     if ((user->has_ipv4 && user->ipv4 && !user->has_ipv6) ||
1199         (user->has_ipv6 && !user->ipv6)) {
1200         ipv6 = 0;
1201     }
1202 
1203     vnet = user->net ? g_strdup(user->net) :
1204            user->ip  ? g_strdup_printf("%s/24", user->ip) :
1205            NULL;
1206 
1207     dnssearch = slirp_dnssearch(user->dnssearch);
1208 
1209     /* all optional fields are initialized to "all bits zero" */
1210 
1211     net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD);
1212     net_init_slirp_configs(user->guestfwd, 0);
1213 
1214     ret = net_slirp_init(peer, "user", name, user->q_restrict,
1215                          ipv4, vnet, user->host,
1216                          ipv6, user->ipv6_prefix, user->ipv6_prefixlen,
1217                          user->ipv6_host, user->hostname, user->tftp,
1218                          user->bootfile, user->dhcpstart,
1219                          user->dns, user->ipv6_dns, user->smb,
1220                          user->smbserver, dnssearch, user->domainname,
1221                          user->tftp_server_name, errp);
1222 
1223     while (slirp_configs) {
1224         config = slirp_configs;
1225         slirp_configs = config->next;
1226         g_free(config);
1227     }
1228 
1229     g_free(vnet);
1230     g_free(dnssearch);
1231 
1232     return ret;
1233 }
1234