xref: /openbmc/qemu/net/slirp.c (revision 806f71ee)
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 in_addr host_addr = { .s_addr = INADDR_ANY };
722     int host_port;
723     char buf[256];
724     const char *src_str, *p;
725     SlirpState *s;
726     int is_udp = 0;
727     int err;
728     const char *arg1 = qdict_get_str(qdict, "arg1");
729     const char *arg2 = qdict_get_try_str(qdict, "arg2");
730 
731     if (arg2) {
732         s = slirp_lookup(mon, arg1);
733         src_str = arg2;
734     } else {
735         s = slirp_lookup(mon, NULL);
736         src_str = arg1;
737     }
738     if (!s) {
739         return;
740     }
741 
742     p = src_str;
743     if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
744         goto fail_syntax;
745     }
746 
747     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
748         is_udp = 0;
749     } else if (!strcmp(buf, "udp")) {
750         is_udp = 1;
751     } else {
752         goto fail_syntax;
753     }
754 
755     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
756         goto fail_syntax;
757     }
758     if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
759         goto fail_syntax;
760     }
761 
762     if (qemu_strtoi(p, NULL, 10, &host_port)) {
763         goto fail_syntax;
764     }
765 
766     err = slirp_remove_hostfwd(s->slirp, is_udp, host_addr, host_port);
767 
768     monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
769                    err ? "not found" : "removed");
770     return;
771 
772  fail_syntax:
773     monitor_printf(mon, "invalid format\n");
774 }
775 
776 static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
777 {
778     struct in_addr host_addr = { .s_addr = INADDR_ANY };
779     struct in_addr guest_addr = { .s_addr = 0 };
780     int host_port, guest_port;
781     const char *p;
782     char buf[256];
783     int is_udp;
784     char *end;
785     const char *fail_reason = "Unknown reason";
786 
787     p = redir_str;
788     if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
789         fail_reason = "No : separators";
790         goto fail_syntax;
791     }
792     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
793         is_udp = 0;
794     } else if (!strcmp(buf, "udp")) {
795         is_udp = 1;
796     } else {
797         fail_reason = "Bad protocol name";
798         goto fail_syntax;
799     }
800 
801     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
802         fail_reason = "Missing : separator";
803         goto fail_syntax;
804     }
805     if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
806         fail_reason = "Bad host address";
807         goto fail_syntax;
808     }
809 
810     if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
811         fail_reason = "Bad host port separator";
812         goto fail_syntax;
813     }
814     host_port = strtol(buf, &end, 0);
815     if (*end != '\0' || host_port < 0 || host_port > 65535) {
816         fail_reason = "Bad host port";
817         goto fail_syntax;
818     }
819 
820     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
821         fail_reason = "Missing guest address";
822         goto fail_syntax;
823     }
824     if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
825         fail_reason = "Bad guest address";
826         goto fail_syntax;
827     }
828 
829     guest_port = strtol(p, &end, 0);
830     if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
831         fail_reason = "Bad guest port";
832         goto fail_syntax;
833     }
834 
835     if (slirp_add_hostfwd(s->slirp, is_udp, host_addr, host_port, guest_addr,
836                           guest_port) < 0) {
837         error_setg(errp, "Could not set up host forwarding rule '%s'",
838                    redir_str);
839         return -1;
840     }
841     return 0;
842 
843  fail_syntax:
844     error_setg(errp, "Invalid host forwarding rule '%s' (%s)", redir_str,
845                fail_reason);
846     return -1;
847 }
848 
849 void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
850 {
851     const char *redir_str;
852     SlirpState *s;
853     const char *arg1 = qdict_get_str(qdict, "arg1");
854     const char *arg2 = qdict_get_try_str(qdict, "arg2");
855 
856     if (arg2) {
857         s = slirp_lookup(mon, arg1);
858         redir_str = arg2;
859     } else {
860         s = slirp_lookup(mon, NULL);
861         redir_str = arg1;
862     }
863     if (s) {
864         Error *err = NULL;
865         if (slirp_hostfwd(s, redir_str, &err) < 0) {
866             error_report_err(err);
867         }
868     }
869 
870 }
871 
872 #if defined(CONFIG_SMBD_COMMAND)
873 
874 /* automatic user mode samba server configuration */
875 static void slirp_smb_cleanup(SlirpState *s)
876 {
877     int ret;
878 
879     if (s->smb_dir) {
880         gchar *cmd = g_strdup_printf("rm -rf %s", s->smb_dir);
881         ret = system(cmd);
882         if (ret == -1 || !WIFEXITED(ret)) {
883             error_report("'%s' failed.", cmd);
884         } else if (WEXITSTATUS(ret)) {
885             error_report("'%s' failed. Error code: %d",
886                          cmd, WEXITSTATUS(ret));
887         }
888         g_free(cmd);
889         g_free(s->smb_dir);
890         s->smb_dir = NULL;
891     }
892 }
893 
894 static int slirp_smb(SlirpState* s, const char *exported_dir,
895                      struct in_addr vserver_addr, Error **errp)
896 {
897     char *smb_conf;
898     char *smb_cmdline;
899     struct passwd *passwd;
900     FILE *f;
901 
902     passwd = getpwuid(geteuid());
903     if (!passwd) {
904         error_setg(errp, "Failed to retrieve user name");
905         return -1;
906     }
907 
908     if (access(CONFIG_SMBD_COMMAND, F_OK)) {
909         error_setg(errp, "Could not find '%s', please install it",
910                    CONFIG_SMBD_COMMAND);
911         return -1;
912     }
913 
914     if (access(exported_dir, R_OK | X_OK)) {
915         error_setg(errp, "Error accessing shared directory '%s': %s",
916                    exported_dir, strerror(errno));
917         return -1;
918     }
919 
920     s->smb_dir = g_dir_make_tmp("qemu-smb.XXXXXX", NULL);
921     if (!s->smb_dir) {
922         error_setg(errp, "Could not create samba server dir");
923         return -1;
924     }
925     smb_conf = g_strdup_printf("%s/%s", s->smb_dir, "smb.conf");
926 
927     f = fopen(smb_conf, "w");
928     if (!f) {
929         slirp_smb_cleanup(s);
930         error_setg(errp,
931                    "Could not create samba server configuration file '%s'",
932                     smb_conf);
933         g_free(smb_conf);
934         return -1;
935     }
936     fprintf(f,
937             "[global]\n"
938             "private dir=%s\n"
939             "interfaces=127.0.0.1\n"
940             "bind interfaces only=yes\n"
941             "pid directory=%s\n"
942             "lock directory=%s\n"
943             "state directory=%s\n"
944             "cache directory=%s\n"
945             "ncalrpc dir=%s/ncalrpc\n"
946             "log file=%s/log.smbd\n"
947             "smb passwd file=%s/smbpasswd\n"
948             "security = user\n"
949             "map to guest = Bad User\n"
950             "load printers = no\n"
951             "printing = bsd\n"
952             "disable spoolss = yes\n"
953             "usershare max shares = 0\n"
954             "[qemu]\n"
955             "path=%s\n"
956             "read only=no\n"
957             "guest ok=yes\n"
958             "force user=%s\n",
959             s->smb_dir,
960             s->smb_dir,
961             s->smb_dir,
962             s->smb_dir,
963             s->smb_dir,
964             s->smb_dir,
965             s->smb_dir,
966             s->smb_dir,
967             exported_dir,
968             passwd->pw_name
969             );
970     fclose(f);
971 
972     smb_cmdline = g_strdup_printf("%s -l %s -s %s",
973              CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
974     g_free(smb_conf);
975 
976     if (slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 139) < 0 ||
977         slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 445) < 0) {
978         slirp_smb_cleanup(s);
979         g_free(smb_cmdline);
980         error_setg(errp, "Conflicting/invalid smbserver address");
981         return -1;
982     }
983     g_free(smb_cmdline);
984     return 0;
985 }
986 
987 #endif /* defined(CONFIG_SMBD_COMMAND) */
988 
989 static int guestfwd_can_read(void *opaque)
990 {
991     struct GuestFwd *fwd = opaque;
992     return slirp_socket_can_recv(fwd->slirp, fwd->server, fwd->port);
993 }
994 
995 static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
996 {
997     struct GuestFwd *fwd = opaque;
998     slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
999 }
1000 
1001 static ssize_t guestfwd_write(const void *buf, size_t len, void *chr)
1002 {
1003     return qemu_chr_fe_write_all(chr, buf, len);
1004 }
1005 
1006 static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
1007 {
1008     /* TODO: IPv6 */
1009     struct in_addr server = { .s_addr = 0 };
1010     struct GuestFwd *fwd;
1011     const char *p;
1012     char buf[128];
1013     char *end;
1014     int port;
1015 
1016     p = config_str;
1017     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1018         goto fail_syntax;
1019     }
1020     if (strcmp(buf, "tcp") && buf[0] != '\0') {
1021         goto fail_syntax;
1022     }
1023     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1024         goto fail_syntax;
1025     }
1026     if (buf[0] != '\0' && !inet_aton(buf, &server)) {
1027         goto fail_syntax;
1028     }
1029     if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
1030         goto fail_syntax;
1031     }
1032     port = strtol(buf, &end, 10);
1033     if (*end != '\0' || port < 1 || port > 65535) {
1034         goto fail_syntax;
1035     }
1036 
1037     snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
1038 
1039     if (g_str_has_prefix(p, "cmd:")) {
1040         if (slirp_add_exec(s->slirp, &p[4], &server, port) < 0) {
1041             error_setg(errp, "Conflicting/invalid host:port in guest "
1042                        "forwarding rule '%s'", config_str);
1043             return -1;
1044         }
1045     } else {
1046         Error *err = NULL;
1047         /*
1048          * FIXME: sure we want to support implicit
1049          * muxed monitors here?
1050          */
1051         Chardev *chr = qemu_chr_new_mux_mon(buf, p, NULL);
1052 
1053         if (!chr) {
1054             error_setg(errp, "Could not open guest forwarding device '%s'",
1055                        buf);
1056             return -1;
1057         }
1058 
1059         fwd = g_new(struct GuestFwd, 1);
1060         qemu_chr_fe_init(&fwd->hd, chr, &err);
1061         if (err) {
1062             error_propagate(errp, err);
1063             object_unparent(OBJECT(chr));
1064             g_free(fwd);
1065             return -1;
1066         }
1067 
1068         if (slirp_add_guestfwd(s->slirp, guestfwd_write, &fwd->hd,
1069                                &server, port) < 0) {
1070             error_setg(errp, "Conflicting/invalid host:port in guest "
1071                        "forwarding rule '%s'", config_str);
1072             qemu_chr_fe_deinit(&fwd->hd, true);
1073             g_free(fwd);
1074             return -1;
1075         }
1076         fwd->server = server;
1077         fwd->port = port;
1078         fwd->slirp = s->slirp;
1079 
1080         qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
1081                                  NULL, NULL, fwd, NULL, true);
1082         s->fwd = g_slist_append(s->fwd, fwd);
1083     }
1084     return 0;
1085 
1086  fail_syntax:
1087     error_setg(errp, "Invalid guest forwarding rule '%s'", config_str);
1088     return -1;
1089 }
1090 
1091 void hmp_info_usernet(Monitor *mon, const QDict *qdict)
1092 {
1093     SlirpState *s;
1094 
1095     QTAILQ_FOREACH(s, &slirp_stacks, entry) {
1096         int id;
1097         bool got_hub_id = net_hub_id_for_client(&s->nc, &id) == 0;
1098         char *info = slirp_connection_info(s->slirp);
1099         monitor_printf(mon, "Hub %d (%s):\n%s",
1100                        got_hub_id ? id : -1,
1101                        s->nc.name, info);
1102         g_free(info);
1103     }
1104 }
1105 
1106 static void
1107 net_init_slirp_configs(const StringList *fwd, int flags)
1108 {
1109     while (fwd) {
1110         struct slirp_config_str *config;
1111 
1112         config = g_malloc0(sizeof(*config));
1113         pstrcpy(config->str, sizeof(config->str), fwd->value->str);
1114         config->flags = flags;
1115         config->next = slirp_configs;
1116         slirp_configs = config;
1117 
1118         fwd = fwd->next;
1119     }
1120 }
1121 
1122 static const char **slirp_dnssearch(const StringList *dnsname)
1123 {
1124     const StringList *c = dnsname;
1125     size_t i = 0, num_opts = 0;
1126     const char **ret;
1127 
1128     while (c) {
1129         num_opts++;
1130         c = c->next;
1131     }
1132 
1133     if (num_opts == 0) {
1134         return NULL;
1135     }
1136 
1137     ret = g_malloc((num_opts + 1) * sizeof(*ret));
1138     c = dnsname;
1139     while (c) {
1140         ret[i++] = c->value->str;
1141         c = c->next;
1142     }
1143     ret[i] = NULL;
1144     return ret;
1145 }
1146 
1147 int net_init_slirp(const Netdev *netdev, const char *name,
1148                    NetClientState *peer, Error **errp)
1149 {
1150     struct slirp_config_str *config;
1151     char *vnet;
1152     int ret;
1153     const NetdevUserOptions *user;
1154     const char **dnssearch;
1155     bool ipv4 = true, ipv6 = true;
1156 
1157     assert(netdev->type == NET_CLIENT_DRIVER_USER);
1158     user = &netdev->u.user;
1159 
1160     if ((user->has_ipv6 && user->ipv6 && !user->has_ipv4) ||
1161         (user->has_ipv4 && !user->ipv4)) {
1162         ipv4 = 0;
1163     }
1164     if ((user->has_ipv4 && user->ipv4 && !user->has_ipv6) ||
1165         (user->has_ipv6 && !user->ipv6)) {
1166         ipv6 = 0;
1167     }
1168 
1169     vnet = user->net ? g_strdup(user->net) :
1170            user->ip  ? g_strdup_printf("%s/24", user->ip) :
1171            NULL;
1172 
1173     dnssearch = slirp_dnssearch(user->dnssearch);
1174 
1175     /* all optional fields are initialized to "all bits zero" */
1176 
1177     net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD);
1178     net_init_slirp_configs(user->guestfwd, 0);
1179 
1180     ret = net_slirp_init(peer, "user", name, user->q_restrict,
1181                          ipv4, vnet, user->host,
1182                          ipv6, user->ipv6_prefix, user->ipv6_prefixlen,
1183                          user->ipv6_host, user->hostname, user->tftp,
1184                          user->bootfile, user->dhcpstart,
1185                          user->dns, user->ipv6_dns, user->smb,
1186                          user->smbserver, dnssearch, user->domainname,
1187                          user->tftp_server_name, errp);
1188 
1189     while (slirp_configs) {
1190         config = slirp_configs;
1191         slirp_configs = config->next;
1192         g_free(config);
1193     }
1194 
1195     g_free(vnet);
1196     g_free(dnssearch);
1197 
1198     return ret;
1199 }
1200