slirp.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  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. #include "qemu/osdep.h"
  25. #include "net/slirp.h"
  26. #ifndef _WIN32
  27. #include <pwd.h>
  28. #include <sys/wait.h>
  29. #endif
  30. #include "net/net.h"
  31. #include "clients.h"
  32. #include "hub.h"
  33. #include "monitor/monitor.h"
  34. #include "qemu/error-report.h"
  35. #include "qemu/sockets.h"
  36. #include "slirp/libslirp.h"
  37. #include "slirp/ip6.h"
  38. #include "sysemu/char.h"
  39. #include "sysemu/sysemu.h"
  40. #include "qemu/cutils.h"
  41. #include "qapi/error.h"
  42. static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
  43. {
  44. const char *p, *p1;
  45. int len;
  46. p = *pp;
  47. p1 = strchr(p, sep);
  48. if (!p1)
  49. return -1;
  50. len = p1 - p;
  51. p1++;
  52. if (buf_size > 0) {
  53. if (len > buf_size - 1)
  54. len = buf_size - 1;
  55. memcpy(buf, p, len);
  56. buf[len] = '\0';
  57. }
  58. *pp = p1;
  59. return 0;
  60. }
  61. /* slirp network adapter */
  62. #define SLIRP_CFG_HOSTFWD 1
  63. #define SLIRP_CFG_LEGACY 2
  64. struct slirp_config_str {
  65. struct slirp_config_str *next;
  66. int flags;
  67. char str[1024];
  68. int legacy_format;
  69. };
  70. typedef struct SlirpState {
  71. NetClientState nc;
  72. QTAILQ_ENTRY(SlirpState) entry;
  73. Slirp *slirp;
  74. Notifier exit_notifier;
  75. #ifndef _WIN32
  76. char smb_dir[128];
  77. #endif
  78. } SlirpState;
  79. static struct slirp_config_str *slirp_configs;
  80. const char *legacy_tftp_prefix;
  81. const char *legacy_bootp_filename;
  82. static QTAILQ_HEAD(slirp_stacks, SlirpState) slirp_stacks =
  83. QTAILQ_HEAD_INITIALIZER(slirp_stacks);
  84. static int slirp_hostfwd(SlirpState *s, const char *redir_str,
  85. int legacy_format);
  86. static int slirp_guestfwd(SlirpState *s, const char *config_str,
  87. int legacy_format);
  88. #ifndef _WIN32
  89. static const char *legacy_smb_export;
  90. static int slirp_smb(SlirpState *s, const char *exported_dir,
  91. struct in_addr vserver_addr);
  92. static void slirp_smb_cleanup(SlirpState *s);
  93. #else
  94. static inline void slirp_smb_cleanup(SlirpState *s) { }
  95. #endif
  96. void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
  97. {
  98. SlirpState *s = opaque;
  99. qemu_send_packet(&s->nc, pkt, pkt_len);
  100. }
  101. static ssize_t net_slirp_receive(NetClientState *nc, const uint8_t *buf, size_t size)
  102. {
  103. SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
  104. slirp_input(s->slirp, buf, size);
  105. return size;
  106. }
  107. static void slirp_smb_exit(Notifier *n, void *data)
  108. {
  109. SlirpState *s = container_of(n, SlirpState, exit_notifier);
  110. slirp_smb_cleanup(s);
  111. }
  112. static void net_slirp_cleanup(NetClientState *nc)
  113. {
  114. SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
  115. slirp_cleanup(s->slirp);
  116. if (s->exit_notifier.notify) {
  117. qemu_remove_exit_notifier(&s->exit_notifier);
  118. }
  119. slirp_smb_cleanup(s);
  120. QTAILQ_REMOVE(&slirp_stacks, s, entry);
  121. }
  122. static NetClientInfo net_slirp_info = {
  123. .type = NET_CLIENT_DRIVER_USER,
  124. .size = sizeof(SlirpState),
  125. .receive = net_slirp_receive,
  126. .cleanup = net_slirp_cleanup,
  127. };
  128. static int net_slirp_init(NetClientState *peer, const char *model,
  129. const char *name, int restricted,
  130. bool ipv4, const char *vnetwork, const char *vhost,
  131. bool ipv6, const char *vprefix6, int vprefix6_len,
  132. const char *vhost6,
  133. const char *vhostname, const char *tftp_export,
  134. const char *bootfile, const char *vdhcp_start,
  135. const char *vnameserver, const char *vnameserver6,
  136. const char *smb_export, const char *vsmbserver,
  137. const char **dnssearch)
  138. {
  139. /* default settings according to historic slirp */
  140. struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
  141. struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */
  142. struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
  143. struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
  144. struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
  145. struct in6_addr ip6_prefix;
  146. struct in6_addr ip6_host;
  147. struct in6_addr ip6_dns;
  148. #ifndef _WIN32
  149. struct in_addr smbsrv = { .s_addr = 0 };
  150. #endif
  151. NetClientState *nc;
  152. SlirpState *s;
  153. char buf[20];
  154. uint32_t addr;
  155. int shift;
  156. char *end;
  157. struct slirp_config_str *config;
  158. if (!ipv4 && (vnetwork || vhost || vnameserver)) {
  159. return -1;
  160. }
  161. if (!ipv6 && (vprefix6 || vhost6 || vnameserver6)) {
  162. return -1;
  163. }
  164. if (!ipv4 && !ipv6) {
  165. /* It doesn't make sense to disable both */
  166. return -1;
  167. }
  168. if (!tftp_export) {
  169. tftp_export = legacy_tftp_prefix;
  170. }
  171. if (!bootfile) {
  172. bootfile = legacy_bootp_filename;
  173. }
  174. if (vnetwork) {
  175. if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
  176. if (!inet_aton(vnetwork, &net)) {
  177. return -1;
  178. }
  179. addr = ntohl(net.s_addr);
  180. if (!(addr & 0x80000000)) {
  181. mask.s_addr = htonl(0xff000000); /* class A */
  182. } else if ((addr & 0xfff00000) == 0xac100000) {
  183. mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
  184. } else if ((addr & 0xc0000000) == 0x80000000) {
  185. mask.s_addr = htonl(0xffff0000); /* class B */
  186. } else if ((addr & 0xffff0000) == 0xc0a80000) {
  187. mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
  188. } else if ((addr & 0xffff0000) == 0xc6120000) {
  189. mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
  190. } else if ((addr & 0xe0000000) == 0xe0000000) {
  191. mask.s_addr = htonl(0xffffff00); /* class C */
  192. } else {
  193. mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
  194. }
  195. } else {
  196. if (!inet_aton(buf, &net)) {
  197. return -1;
  198. }
  199. shift = strtol(vnetwork, &end, 10);
  200. if (*end != '\0') {
  201. if (!inet_aton(vnetwork, &mask)) {
  202. return -1;
  203. }
  204. } else if (shift < 4 || shift > 32) {
  205. return -1;
  206. } else {
  207. mask.s_addr = htonl(0xffffffff << (32 - shift));
  208. }
  209. }
  210. net.s_addr &= mask.s_addr;
  211. host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
  212. dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
  213. dns.s_addr = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
  214. }
  215. if (vhost && !inet_aton(vhost, &host)) {
  216. return -1;
  217. }
  218. if ((host.s_addr & mask.s_addr) != net.s_addr) {
  219. return -1;
  220. }
  221. if (vnameserver && !inet_aton(vnameserver, &dns)) {
  222. return -1;
  223. }
  224. if ((dns.s_addr & mask.s_addr) != net.s_addr ||
  225. dns.s_addr == host.s_addr) {
  226. return -1;
  227. }
  228. if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
  229. return -1;
  230. }
  231. if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
  232. dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
  233. return -1;
  234. }
  235. #ifndef _WIN32
  236. if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
  237. return -1;
  238. }
  239. #endif
  240. #if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
  241. /* No inet_pton helper before Vista... */
  242. if (vprefix6) {
  243. /* Unsupported */
  244. return -1;
  245. }
  246. memset(&ip6_prefix, 0, sizeof(ip6_prefix));
  247. ip6_prefix.s6_addr[0] = 0xfe;
  248. ip6_prefix.s6_addr[1] = 0xc0;
  249. #else
  250. if (!vprefix6) {
  251. vprefix6 = "fec0::";
  252. }
  253. if (!inet_pton(AF_INET6, vprefix6, &ip6_prefix)) {
  254. return -1;
  255. }
  256. #endif
  257. if (!vprefix6_len) {
  258. vprefix6_len = 64;
  259. }
  260. if (vprefix6_len < 0 || vprefix6_len > 126) {
  261. return -1;
  262. }
  263. if (vhost6) {
  264. #if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
  265. return -1;
  266. #else
  267. if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
  268. return -1;
  269. }
  270. if (!in6_equal_net(&ip6_prefix, &ip6_host, vprefix6_len)) {
  271. return -1;
  272. }
  273. #endif
  274. } else {
  275. ip6_host = ip6_prefix;
  276. ip6_host.s6_addr[15] |= 2;
  277. }
  278. if (vnameserver6) {
  279. #if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
  280. return -1;
  281. #else
  282. if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
  283. return -1;
  284. }
  285. if (!in6_equal_net(&ip6_prefix, &ip6_dns, vprefix6_len)) {
  286. return -1;
  287. }
  288. #endif
  289. } else {
  290. ip6_dns = ip6_prefix;
  291. ip6_dns.s6_addr[15] |= 3;
  292. }
  293. nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
  294. snprintf(nc->info_str, sizeof(nc->info_str),
  295. "net=%s,restrict=%s", inet_ntoa(net),
  296. restricted ? "on" : "off");
  297. s = DO_UPCAST(SlirpState, nc, nc);
  298. s->slirp = slirp_init(restricted, ipv4, net, mask, host,
  299. ipv6, ip6_prefix, vprefix6_len, ip6_host,
  300. vhostname, tftp_export, bootfile, dhcp,
  301. dns, ip6_dns, dnssearch, s);
  302. QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
  303. for (config = slirp_configs; config; config = config->next) {
  304. if (config->flags & SLIRP_CFG_HOSTFWD) {
  305. if (slirp_hostfwd(s, config->str,
  306. config->flags & SLIRP_CFG_LEGACY) < 0)
  307. goto error;
  308. } else {
  309. if (slirp_guestfwd(s, config->str,
  310. config->flags & SLIRP_CFG_LEGACY) < 0)
  311. goto error;
  312. }
  313. }
  314. #ifndef _WIN32
  315. if (!smb_export) {
  316. smb_export = legacy_smb_export;
  317. }
  318. if (smb_export) {
  319. if (slirp_smb(s, smb_export, smbsrv) < 0)
  320. goto error;
  321. }
  322. #endif
  323. s->exit_notifier.notify = slirp_smb_exit;
  324. qemu_add_exit_notifier(&s->exit_notifier);
  325. return 0;
  326. error:
  327. qemu_del_net_client(nc);
  328. return -1;
  329. }
  330. static SlirpState *slirp_lookup(Monitor *mon, const char *vlan,
  331. const char *stack)
  332. {
  333. if (vlan) {
  334. NetClientState *nc;
  335. nc = net_hub_find_client_by_name(strtol(vlan, NULL, 0), stack);
  336. if (!nc) {
  337. monitor_printf(mon, "unrecognized (vlan-id, stackname) pair\n");
  338. return NULL;
  339. }
  340. if (strcmp(nc->model, "user")) {
  341. monitor_printf(mon, "invalid device specified\n");
  342. return NULL;
  343. }
  344. return DO_UPCAST(SlirpState, nc, nc);
  345. } else {
  346. if (QTAILQ_EMPTY(&slirp_stacks)) {
  347. monitor_printf(mon, "user mode network stack not in use\n");
  348. return NULL;
  349. }
  350. return QTAILQ_FIRST(&slirp_stacks);
  351. }
  352. }
  353. void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
  354. {
  355. struct in_addr host_addr = { .s_addr = INADDR_ANY };
  356. int host_port;
  357. char buf[256];
  358. const char *src_str, *p;
  359. SlirpState *s;
  360. int is_udp = 0;
  361. int err;
  362. const char *arg1 = qdict_get_str(qdict, "arg1");
  363. const char *arg2 = qdict_get_try_str(qdict, "arg2");
  364. const char *arg3 = qdict_get_try_str(qdict, "arg3");
  365. if (arg2) {
  366. s = slirp_lookup(mon, arg1, arg2);
  367. src_str = arg3;
  368. } else {
  369. s = slirp_lookup(mon, NULL, NULL);
  370. src_str = arg1;
  371. }
  372. if (!s) {
  373. return;
  374. }
  375. p = src_str;
  376. if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
  377. goto fail_syntax;
  378. }
  379. if (!strcmp(buf, "tcp") || buf[0] == '\0') {
  380. is_udp = 0;
  381. } else if (!strcmp(buf, "udp")) {
  382. is_udp = 1;
  383. } else {
  384. goto fail_syntax;
  385. }
  386. if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
  387. goto fail_syntax;
  388. }
  389. if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
  390. goto fail_syntax;
  391. }
  392. host_port = atoi(p);
  393. err = slirp_remove_hostfwd(s->slirp, is_udp, host_addr, host_port);
  394. monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
  395. err ? "not found" : "removed");
  396. return;
  397. fail_syntax:
  398. monitor_printf(mon, "invalid format\n");
  399. }
  400. static int slirp_hostfwd(SlirpState *s, const char *redir_str,
  401. int legacy_format)
  402. {
  403. struct in_addr host_addr = { .s_addr = INADDR_ANY };
  404. struct in_addr guest_addr = { .s_addr = 0 };
  405. int host_port, guest_port;
  406. const char *p;
  407. char buf[256];
  408. int is_udp;
  409. char *end;
  410. p = redir_str;
  411. if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
  412. goto fail_syntax;
  413. }
  414. if (!strcmp(buf, "tcp") || buf[0] == '\0') {
  415. is_udp = 0;
  416. } else if (!strcmp(buf, "udp")) {
  417. is_udp = 1;
  418. } else {
  419. goto fail_syntax;
  420. }
  421. if (!legacy_format) {
  422. if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
  423. goto fail_syntax;
  424. }
  425. if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
  426. goto fail_syntax;
  427. }
  428. }
  429. if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
  430. goto fail_syntax;
  431. }
  432. host_port = strtol(buf, &end, 0);
  433. if (*end != '\0' || host_port < 1 || host_port > 65535) {
  434. goto fail_syntax;
  435. }
  436. if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
  437. goto fail_syntax;
  438. }
  439. if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
  440. goto fail_syntax;
  441. }
  442. guest_port = strtol(p, &end, 0);
  443. if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
  444. goto fail_syntax;
  445. }
  446. if (slirp_add_hostfwd(s->slirp, is_udp, host_addr, host_port, guest_addr,
  447. guest_port) < 0) {
  448. error_report("could not set up host forwarding rule '%s'",
  449. redir_str);
  450. return -1;
  451. }
  452. return 0;
  453. fail_syntax:
  454. error_report("invalid host forwarding rule '%s'", redir_str);
  455. return -1;
  456. }
  457. void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
  458. {
  459. const char *redir_str;
  460. SlirpState *s;
  461. const char *arg1 = qdict_get_str(qdict, "arg1");
  462. const char *arg2 = qdict_get_try_str(qdict, "arg2");
  463. const char *arg3 = qdict_get_try_str(qdict, "arg3");
  464. if (arg2) {
  465. s = slirp_lookup(mon, arg1, arg2);
  466. redir_str = arg3;
  467. } else {
  468. s = slirp_lookup(mon, NULL, NULL);
  469. redir_str = arg1;
  470. }
  471. if (s) {
  472. slirp_hostfwd(s, redir_str, 0);
  473. }
  474. }
  475. int net_slirp_redir(const char *redir_str)
  476. {
  477. struct slirp_config_str *config;
  478. if (QTAILQ_EMPTY(&slirp_stacks)) {
  479. config = g_malloc(sizeof(*config));
  480. pstrcpy(config->str, sizeof(config->str), redir_str);
  481. config->flags = SLIRP_CFG_HOSTFWD | SLIRP_CFG_LEGACY;
  482. config->next = slirp_configs;
  483. slirp_configs = config;
  484. return 0;
  485. }
  486. return slirp_hostfwd(QTAILQ_FIRST(&slirp_stacks), redir_str, 1);
  487. }
  488. #ifndef _WIN32
  489. /* automatic user mode samba server configuration */
  490. static void slirp_smb_cleanup(SlirpState *s)
  491. {
  492. char cmd[128];
  493. int ret;
  494. if (s->smb_dir[0] != '\0') {
  495. snprintf(cmd, sizeof(cmd), "rm -rf %s", s->smb_dir);
  496. ret = system(cmd);
  497. if (ret == -1 || !WIFEXITED(ret)) {
  498. error_report("'%s' failed.", cmd);
  499. } else if (WEXITSTATUS(ret)) {
  500. error_report("'%s' failed. Error code: %d",
  501. cmd, WEXITSTATUS(ret));
  502. }
  503. s->smb_dir[0] = '\0';
  504. }
  505. }
  506. static int slirp_smb(SlirpState* s, const char *exported_dir,
  507. struct in_addr vserver_addr)
  508. {
  509. char smb_conf[128];
  510. char smb_cmdline[128];
  511. struct passwd *passwd;
  512. FILE *f;
  513. passwd = getpwuid(geteuid());
  514. if (!passwd) {
  515. error_report("failed to retrieve user name");
  516. return -1;
  517. }
  518. if (access(CONFIG_SMBD_COMMAND, F_OK)) {
  519. error_report("could not find '%s', please install it",
  520. CONFIG_SMBD_COMMAND);
  521. return -1;
  522. }
  523. if (access(exported_dir, R_OK | X_OK)) {
  524. error_report("error accessing shared directory '%s': %s",
  525. exported_dir, strerror(errno));
  526. return -1;
  527. }
  528. snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.XXXXXX");
  529. if (!mkdtemp(s->smb_dir)) {
  530. error_report("could not create samba server dir '%s'", s->smb_dir);
  531. s->smb_dir[0] = 0;
  532. return -1;
  533. }
  534. snprintf(smb_conf, sizeof(smb_conf), "%s/%s", s->smb_dir, "smb.conf");
  535. f = fopen(smb_conf, "w");
  536. if (!f) {
  537. slirp_smb_cleanup(s);
  538. error_report("could not create samba server configuration file '%s'",
  539. smb_conf);
  540. return -1;
  541. }
  542. fprintf(f,
  543. "[global]\n"
  544. "private dir=%s\n"
  545. "interfaces=127.0.0.1\n"
  546. "bind interfaces only=yes\n"
  547. "pid directory=%s\n"
  548. "lock directory=%s\n"
  549. "state directory=%s\n"
  550. "cache directory=%s\n"
  551. "ncalrpc dir=%s/ncalrpc\n"
  552. "log file=%s/log.smbd\n"
  553. "smb passwd file=%s/smbpasswd\n"
  554. "security = user\n"
  555. "map to guest = Bad User\n"
  556. "load printers = no\n"
  557. "printing = bsd\n"
  558. "disable spoolss = yes\n"
  559. "usershare max shares = 0\n"
  560. "[qemu]\n"
  561. "path=%s\n"
  562. "read only=no\n"
  563. "guest ok=yes\n"
  564. "force user=%s\n",
  565. s->smb_dir,
  566. s->smb_dir,
  567. s->smb_dir,
  568. s->smb_dir,
  569. s->smb_dir,
  570. s->smb_dir,
  571. s->smb_dir,
  572. s->smb_dir,
  573. exported_dir,
  574. passwd->pw_name
  575. );
  576. fclose(f);
  577. snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -l %s -s %s",
  578. CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
  579. if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0 ||
  580. slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 445) < 0) {
  581. slirp_smb_cleanup(s);
  582. error_report("conflicting/invalid smbserver address");
  583. return -1;
  584. }
  585. return 0;
  586. }
  587. /* automatic user mode samba server configuration (legacy interface) */
  588. int net_slirp_smb(const char *exported_dir)
  589. {
  590. struct in_addr vserver_addr = { .s_addr = 0 };
  591. if (legacy_smb_export) {
  592. fprintf(stderr, "-smb given twice\n");
  593. return -1;
  594. }
  595. legacy_smb_export = exported_dir;
  596. if (!QTAILQ_EMPTY(&slirp_stacks)) {
  597. return slirp_smb(QTAILQ_FIRST(&slirp_stacks), exported_dir,
  598. vserver_addr);
  599. }
  600. return 0;
  601. }
  602. #endif /* !defined(_WIN32) */
  603. struct GuestFwd {
  604. CharBackend hd;
  605. struct in_addr server;
  606. int port;
  607. Slirp *slirp;
  608. };
  609. static int guestfwd_can_read(void *opaque)
  610. {
  611. struct GuestFwd *fwd = opaque;
  612. return slirp_socket_can_recv(fwd->slirp, fwd->server, fwd->port);
  613. }
  614. static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
  615. {
  616. struct GuestFwd *fwd = opaque;
  617. slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
  618. }
  619. static int slirp_guestfwd(SlirpState *s, const char *config_str,
  620. int legacy_format)
  621. {
  622. struct in_addr server = { .s_addr = 0 };
  623. struct GuestFwd *fwd;
  624. const char *p;
  625. char buf[128];
  626. char *end;
  627. int port;
  628. p = config_str;
  629. if (legacy_format) {
  630. if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
  631. goto fail_syntax;
  632. }
  633. } else {
  634. if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
  635. goto fail_syntax;
  636. }
  637. if (strcmp(buf, "tcp") && buf[0] != '\0') {
  638. goto fail_syntax;
  639. }
  640. if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
  641. goto fail_syntax;
  642. }
  643. if (buf[0] != '\0' && !inet_aton(buf, &server)) {
  644. goto fail_syntax;
  645. }
  646. if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
  647. goto fail_syntax;
  648. }
  649. }
  650. port = strtol(buf, &end, 10);
  651. if (*end != '\0' || port < 1 || port > 65535) {
  652. goto fail_syntax;
  653. }
  654. snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
  655. if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) {
  656. if (slirp_add_exec(s->slirp, 0, &p[4], &server, port) < 0) {
  657. error_report("conflicting/invalid host:port in guest forwarding "
  658. "rule '%s'", config_str);
  659. return -1;
  660. }
  661. } else {
  662. Error *err = NULL;
  663. Chardev *chr = qemu_chr_new(buf, p);
  664. if (!chr) {
  665. error_report("could not open guest forwarding device '%s'", buf);
  666. return -1;
  667. }
  668. fwd = g_new(struct GuestFwd, 1);
  669. qemu_chr_fe_init(&fwd->hd, chr, &err);
  670. if (err) {
  671. error_report_err(err);
  672. g_free(fwd);
  673. return -1;
  674. }
  675. if (slirp_add_exec(s->slirp, 3, &fwd->hd, &server, port) < 0) {
  676. error_report("conflicting/invalid host:port in guest forwarding "
  677. "rule '%s'", config_str);
  678. g_free(fwd);
  679. return -1;
  680. }
  681. fwd->server = server;
  682. fwd->port = port;
  683. fwd->slirp = s->slirp;
  684. qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
  685. NULL, fwd, NULL, true);
  686. }
  687. return 0;
  688. fail_syntax:
  689. error_report("invalid guest forwarding rule '%s'", config_str);
  690. return -1;
  691. }
  692. void hmp_info_usernet(Monitor *mon, const QDict *qdict)
  693. {
  694. SlirpState *s;
  695. QTAILQ_FOREACH(s, &slirp_stacks, entry) {
  696. int id;
  697. bool got_vlan_id = net_hub_id_for_client(&s->nc, &id) == 0;
  698. monitor_printf(mon, "VLAN %d (%s):\n",
  699. got_vlan_id ? id : -1,
  700. s->nc.name);
  701. slirp_connection_info(s->slirp, mon);
  702. }
  703. }
  704. static void
  705. net_init_slirp_configs(const StringList *fwd, int flags)
  706. {
  707. while (fwd) {
  708. struct slirp_config_str *config;
  709. config = g_malloc0(sizeof(*config));
  710. pstrcpy(config->str, sizeof(config->str), fwd->value->str);
  711. config->flags = flags;
  712. config->next = slirp_configs;
  713. slirp_configs = config;
  714. fwd = fwd->next;
  715. }
  716. }
  717. static const char **slirp_dnssearch(const StringList *dnsname)
  718. {
  719. const StringList *c = dnsname;
  720. size_t i = 0, num_opts = 0;
  721. const char **ret;
  722. while (c) {
  723. num_opts++;
  724. c = c->next;
  725. }
  726. if (num_opts == 0) {
  727. return NULL;
  728. }
  729. ret = g_malloc((num_opts + 1) * sizeof(*ret));
  730. c = dnsname;
  731. while (c) {
  732. ret[i++] = c->value->str;
  733. c = c->next;
  734. }
  735. ret[i] = NULL;
  736. return ret;
  737. }
  738. int net_init_slirp(const Netdev *netdev, const char *name,
  739. NetClientState *peer, Error **errp)
  740. {
  741. /* FIXME error_setg(errp, ...) on failure */
  742. struct slirp_config_str *config;
  743. char *vnet;
  744. int ret;
  745. const NetdevUserOptions *user;
  746. const char **dnssearch;
  747. bool ipv4 = true, ipv6 = true;
  748. assert(netdev->type == NET_CLIENT_DRIVER_USER);
  749. user = &netdev->u.user;
  750. if ((user->has_ipv6 && user->ipv6 && !user->has_ipv4) ||
  751. (user->has_ipv4 && !user->ipv4)) {
  752. ipv4 = 0;
  753. }
  754. if ((user->has_ipv4 && user->ipv4 && !user->has_ipv6) ||
  755. (user->has_ipv6 && !user->ipv6)) {
  756. ipv6 = 0;
  757. }
  758. vnet = user->has_net ? g_strdup(user->net) :
  759. user->has_ip ? g_strdup_printf("%s/24", user->ip) :
  760. NULL;
  761. dnssearch = slirp_dnssearch(user->dnssearch);
  762. /* all optional fields are initialized to "all bits zero" */
  763. net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD);
  764. net_init_slirp_configs(user->guestfwd, 0);
  765. ret = net_slirp_init(peer, "user", name, user->q_restrict,
  766. ipv4, vnet, user->host,
  767. ipv6, user->ipv6_prefix, user->ipv6_prefixlen,
  768. user->ipv6_host, user->hostname, user->tftp,
  769. user->bootfile, user->dhcpstart,
  770. user->dns, user->ipv6_dns, user->smb,
  771. user->smbserver, dnssearch);
  772. while (slirp_configs) {
  773. config = slirp_configs;
  774. slirp_configs = config->next;
  775. g_free(config);
  776. }
  777. g_free(vnet);
  778. g_free(dnssearch);
  779. return ret;
  780. }
  781. int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret)
  782. {
  783. if (strcmp(opts_list->name, "net") != 0 ||
  784. strncmp(optarg, "channel,", strlen("channel,")) != 0) {
  785. return 0;
  786. }
  787. error_report("The '-net channel' option is deprecated. "
  788. "Please use '-netdev user,guestfwd=...' instead.");
  789. /* handle legacy -net channel,port:chr */
  790. optarg += strlen("channel,");
  791. if (QTAILQ_EMPTY(&slirp_stacks)) {
  792. struct slirp_config_str *config;
  793. config = g_malloc(sizeof(*config));
  794. pstrcpy(config->str, sizeof(config->str), optarg);
  795. config->flags = SLIRP_CFG_LEGACY;
  796. config->next = slirp_configs;
  797. slirp_configs = config;
  798. *ret = 0;
  799. } else {
  800. *ret = slirp_guestfwd(QTAILQ_FIRST(&slirp_stacks), optarg, 1);
  801. }
  802. return 1;
  803. }