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