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