|
|
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 "qemu_socket.h"
34: #include "slirp/libslirp.h"
35:
36: static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
37: {
38: const char *p, *p1;
39: int len;
40: p = *pp;
41: p1 = strchr(p, sep);
42: if (!p1)
43: return -1;
44: len = p1 - p;
45: p1++;
46: if (buf_size > 0) {
47: if (len > buf_size - 1)
48: len = buf_size - 1;
49: memcpy(buf, p, len);
50: buf[len] = '\0';
51: }
52: *pp = p1;
53: return 0;
54: }
55:
56: /* slirp network adapter */
57:
58: #define SLIRP_CFG_HOSTFWD 1
59: #define SLIRP_CFG_LEGACY 2
60:
61: struct slirp_config_str {
62: struct slirp_config_str *next;
63: int flags;
64: char str[1024];
65: int legacy_format;
66: };
67:
68: typedef struct SlirpState {
69: VLANClientState nc;
70: QTAILQ_ENTRY(SlirpState) entry;
71: Slirp *slirp;
72: #ifndef _WIN32
73: char smb_dir[128];
74: #endif
75: } SlirpState;
76:
77: static struct slirp_config_str *slirp_configs;
78: const char *legacy_tftp_prefix;
79: const char *legacy_bootp_filename;
80: static QTAILQ_HEAD(slirp_stacks, SlirpState) slirp_stacks =
81: QTAILQ_HEAD_INITIALIZER(slirp_stacks);
82:
83: static int slirp_hostfwd(SlirpState *s, const char *redir_str,
84: int legacy_format);
85: static int slirp_guestfwd(SlirpState *s, const char *config_str,
86: int legacy_format);
87:
88: #ifndef _WIN32
89: static const char *legacy_smb_export;
90:
91: static int slirp_smb(SlirpState *s, const char *exported_dir,
92: struct in_addr vserver_addr);
93: static void slirp_smb_cleanup(SlirpState *s);
94: #else
95: static inline void slirp_smb_cleanup(SlirpState *s) { }
96: #endif
97:
98: int slirp_can_output(void *opaque)
99: {
100: SlirpState *s = opaque;
101:
102: return qemu_can_send_packet(&s->nc);
103: }
104:
105: void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
106: {
107: SlirpState *s = opaque;
108:
109: qemu_send_packet(&s->nc, pkt, pkt_len);
110: }
111:
112: static ssize_t net_slirp_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
113: {
114: SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
115:
116: slirp_input(s->slirp, buf, size);
117:
118: return size;
119: }
120:
121: static void net_slirp_cleanup(VLANClientState *nc)
122: {
123: SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
124:
125: slirp_cleanup(s->slirp);
126: slirp_smb_cleanup(s);
127: QTAILQ_REMOVE(&slirp_stacks, s, entry);
128: }
129:
130: static NetClientInfo net_slirp_info = {
1.1.1.4 ! root 131: .type = NET_CLIENT_TYPE_USER,
1.1 root 132: .size = sizeof(SlirpState),
133: .receive = net_slirp_receive,
134: .cleanup = net_slirp_cleanup,
135: };
136:
137: static int net_slirp_init(VLANState *vlan, const char *model,
138: const char *name, int restricted,
139: const char *vnetwork, const char *vhost,
140: const char *vhostname, const char *tftp_export,
141: const char *bootfile, const char *vdhcp_start,
142: const char *vnameserver, const char *smb_export,
143: const char *vsmbserver)
144: {
145: /* default settings according to historic slirp */
146: struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
147: struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */
148: struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
149: struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
150: struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
151: #ifndef _WIN32
152: struct in_addr smbsrv = { .s_addr = 0 };
153: #endif
154: VLANClientState *nc;
155: SlirpState *s;
156: char buf[20];
157: uint32_t addr;
158: int shift;
159: char *end;
160: struct slirp_config_str *config;
161:
162: if (!tftp_export) {
163: tftp_export = legacy_tftp_prefix;
164: }
165: if (!bootfile) {
166: bootfile = legacy_bootp_filename;
167: }
168:
169: if (vnetwork) {
170: if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
171: if (!inet_aton(vnetwork, &net)) {
172: return -1;
173: }
174: addr = ntohl(net.s_addr);
175: if (!(addr & 0x80000000)) {
176: mask.s_addr = htonl(0xff000000); /* class A */
177: } else if ((addr & 0xfff00000) == 0xac100000) {
178: mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
179: } else if ((addr & 0xc0000000) == 0x80000000) {
180: mask.s_addr = htonl(0xffff0000); /* class B */
181: } else if ((addr & 0xffff0000) == 0xc0a80000) {
182: mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
183: } else if ((addr & 0xffff0000) == 0xc6120000) {
184: mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
185: } else if ((addr & 0xe0000000) == 0xe0000000) {
186: mask.s_addr = htonl(0xffffff00); /* class C */
187: } else {
188: mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
189: }
190: } else {
191: if (!inet_aton(buf, &net)) {
192: return -1;
193: }
194: shift = strtol(vnetwork, &end, 10);
195: if (*end != '\0') {
196: if (!inet_aton(vnetwork, &mask)) {
197: return -1;
198: }
199: } else if (shift < 4 || shift > 32) {
200: return -1;
201: } else {
202: mask.s_addr = htonl(0xffffffff << (32 - shift));
203: }
204: }
205: net.s_addr &= mask.s_addr;
206: host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
207: dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
208: dns.s_addr = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
209: }
210:
211: if (vhost && !inet_aton(vhost, &host)) {
212: return -1;
213: }
214: if ((host.s_addr & mask.s_addr) != net.s_addr) {
215: return -1;
216: }
217:
218: if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
219: return -1;
220: }
221: if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
222: dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
223: return -1;
224: }
225:
226: if (vnameserver && !inet_aton(vnameserver, &dns)) {
227: return -1;
228: }
229: if ((dns.s_addr & mask.s_addr) != net.s_addr ||
230: dns.s_addr == host.s_addr) {
231: return -1;
232: }
233:
234: #ifndef _WIN32
235: if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
236: return -1;
237: }
238: #endif
239:
240: nc = qemu_new_net_client(&net_slirp_info, vlan, NULL, model, name);
241:
242: snprintf(nc->info_str, sizeof(nc->info_str),
1.1.1.4 ! root 243: "net=%s,restrict=%s", inet_ntoa(net),
! 244: restricted ? "on" : "off");
1.1 root 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",
1.1.1.4 ! root 532: CONFIG_SMBD_COMMAND, smb_conf);
1.1 root 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));
1.1.1.4 ! root 618: snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
1.1 root 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;
1.1.1.4 ! root 693: const char *restrict_opt;
1.1 root 694: char *vnet = NULL;
695: int restricted = 0;
696: int ret;
697:
698: vhost = qemu_opt_get(opts, "host");
699: vhostname = qemu_opt_get(opts, "hostname");
700: vdhcp_start = qemu_opt_get(opts, "dhcpstart");
701: vnamesrv = qemu_opt_get(opts, "dns");
702: tftp_export = qemu_opt_get(opts, "tftp");
703: bootfile = qemu_opt_get(opts, "bootfile");
704: smb_export = qemu_opt_get(opts, "smb");
705: vsmbsrv = qemu_opt_get(opts, "smbserver");
706:
1.1.1.4 ! root 707: restrict_opt = qemu_opt_get(opts, "restrict");
! 708: if (restrict_opt) {
! 709: if (!strcmp(restrict_opt, "on") ||
! 710: !strcmp(restrict_opt, "yes") || !strcmp(restrict_opt, "y")) {
! 711: restricted = 1;
! 712: } else if (strcmp(restrict_opt, "off") &&
! 713: strcmp(restrict_opt, "no") && strcmp(restrict_opt, "n")) {
! 714: error_report("invalid option: 'restrict=%s'", restrict_opt);
! 715: return -1;
! 716: }
! 717: }
! 718:
1.1 root 719: if (qemu_opt_get(opts, "ip")) {
720: const char *ip = qemu_opt_get(opts, "ip");
721: int l = strlen(ip) + strlen("/24") + 1;
722:
723: vnet = qemu_malloc(l);
724:
725: /* emulate legacy ip= parameter */
726: pstrcpy(vnet, l, ip);
727: pstrcat(vnet, l, "/24");
728: }
729:
730: if (qemu_opt_get(opts, "net")) {
731: if (vnet) {
732: qemu_free(vnet);
733: }
734: vnet = qemu_strdup(qemu_opt_get(opts, "net"));
735: }
736:
737: qemu_opt_foreach(opts, net_init_slirp_configs, NULL, 0);
738:
739: ret = net_slirp_init(vlan, "user", name, restricted, vnet, vhost,
740: vhostname, tftp_export, bootfile, vdhcp_start,
741: vnamesrv, smb_export, vsmbsrv);
742:
743: while (slirp_configs) {
744: config = slirp_configs;
745: slirp_configs = config->next;
746: qemu_free(config);
747: }
748:
749: qemu_free(vnet);
750:
751: return ret;
752: }
753:
754: int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret)
755: {
756: if (strcmp(opts_list->name, "net") != 0 ||
757: strncmp(optarg, "channel,", strlen("channel,")) != 0) {
758: return 0;
759: }
760:
761: /* handle legacy -net channel,port:chr */
762: optarg += strlen("channel,");
763:
764: if (QTAILQ_EMPTY(&slirp_stacks)) {
765: struct slirp_config_str *config;
766:
767: config = qemu_malloc(sizeof(*config));
768: pstrcpy(config->str, sizeof(config->str), optarg);
769: config->flags = SLIRP_CFG_LEGACY;
770: config->next = slirp_configs;
771: slirp_configs = config;
772: *ret = 0;
773: } else {
774: *ret = slirp_guestfwd(QTAILQ_FIRST(&slirp_stacks), optarg, 1);
775: }
776:
777: return 1;
778: }
779:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.