|
|
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;
1.1.1.5 ! root 308: char buf[256];
1.1 root 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: p = src_str;
1.1.1.5 ! root 329: if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
! 330: goto fail_syntax;
! 331: }
1.1 root 332:
333: if (!strcmp(buf, "tcp") || buf[0] == '\0') {
334: is_udp = 0;
335: } else if (!strcmp(buf, "udp")) {
336: is_udp = 1;
337: } else {
338: goto fail_syntax;
339: }
340:
341: if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
342: goto fail_syntax;
343: }
344: if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
345: goto fail_syntax;
346: }
347:
348: host_port = atoi(p);
349:
350: err = slirp_remove_hostfwd(QTAILQ_FIRST(&slirp_stacks)->slirp, is_udp,
351: host_addr, host_port);
352:
353: monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
354: err ? "removed" : "not found");
355: return;
356:
357: fail_syntax:
358: monitor_printf(mon, "invalid format\n");
359: }
360:
361: static int slirp_hostfwd(SlirpState *s, const char *redir_str,
362: int legacy_format)
363: {
364: struct in_addr host_addr = { .s_addr = INADDR_ANY };
365: struct in_addr guest_addr = { .s_addr = 0 };
366: int host_port, guest_port;
367: const char *p;
368: char buf[256];
369: int is_udp;
370: char *end;
371:
372: p = redir_str;
373: if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
374: goto fail_syntax;
375: }
376: if (!strcmp(buf, "tcp") || buf[0] == '\0') {
377: is_udp = 0;
378: } else if (!strcmp(buf, "udp")) {
379: is_udp = 1;
380: } else {
381: goto fail_syntax;
382: }
383:
384: if (!legacy_format) {
385: if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
386: goto fail_syntax;
387: }
388: if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
389: goto fail_syntax;
390: }
391: }
392:
393: if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
394: goto fail_syntax;
395: }
396: host_port = strtol(buf, &end, 0);
397: if (*end != '\0' || host_port < 1 || host_port > 65535) {
398: goto fail_syntax;
399: }
400:
401: if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
402: goto fail_syntax;
403: }
404: if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
405: goto fail_syntax;
406: }
407:
408: guest_port = strtol(p, &end, 0);
409: if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
410: goto fail_syntax;
411: }
412:
413: if (slirp_add_hostfwd(s->slirp, is_udp, host_addr, host_port, guest_addr,
414: guest_port) < 0) {
1.1.1.3 root 415: error_report("could not set up host forwarding rule '%s'",
416: redir_str);
1.1 root 417: return -1;
418: }
419: return 0;
420:
421: fail_syntax:
1.1.1.3 root 422: error_report("invalid host forwarding rule '%s'", redir_str);
1.1 root 423: return -1;
424: }
425:
426: void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict)
427: {
428: const char *redir_str;
429: SlirpState *s;
430: const char *arg1 = qdict_get_str(qdict, "arg1");
431: const char *arg2 = qdict_get_try_str(qdict, "arg2");
432: const char *arg3 = qdict_get_try_str(qdict, "arg3");
433:
434: if (arg2) {
435: s = slirp_lookup(mon, arg1, arg2);
436: redir_str = arg3;
437: } else {
438: s = slirp_lookup(mon, NULL, NULL);
439: redir_str = arg1;
440: }
441: if (s) {
442: slirp_hostfwd(s, redir_str, 0);
443: }
444:
445: }
446:
447: int net_slirp_redir(const char *redir_str)
448: {
449: struct slirp_config_str *config;
450:
451: if (QTAILQ_EMPTY(&slirp_stacks)) {
1.1.1.5 ! root 452: config = g_malloc(sizeof(*config));
1.1 root 453: pstrcpy(config->str, sizeof(config->str), redir_str);
454: config->flags = SLIRP_CFG_HOSTFWD | SLIRP_CFG_LEGACY;
455: config->next = slirp_configs;
456: slirp_configs = config;
457: return 0;
458: }
459:
460: return slirp_hostfwd(QTAILQ_FIRST(&slirp_stacks), redir_str, 1);
461: }
462:
463: #ifndef _WIN32
464:
465: /* automatic user mode samba server configuration */
466: static void slirp_smb_cleanup(SlirpState *s)
467: {
468: char cmd[128];
1.1.1.3 root 469: int ret;
1.1 root 470:
471: if (s->smb_dir[0] != '\0') {
472: snprintf(cmd, sizeof(cmd), "rm -rf %s", s->smb_dir);
1.1.1.3 root 473: ret = system(cmd);
474: if (ret == -1 || !WIFEXITED(ret)) {
475: error_report("'%s' failed.", cmd);
476: } else if (WEXITSTATUS(ret)) {
477: error_report("'%s' failed. Error code: %d",
478: cmd, WEXITSTATUS(ret));
479: }
1.1 root 480: s->smb_dir[0] = '\0';
481: }
482: }
483:
484: static int slirp_smb(SlirpState* s, const char *exported_dir,
485: struct in_addr vserver_addr)
486: {
487: static int instance;
488: char smb_conf[128];
489: char smb_cmdline[128];
490: FILE *f;
491:
492: snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
493: (long)getpid(), instance++);
494: if (mkdir(s->smb_dir, 0700) < 0) {
1.1.1.3 root 495: error_report("could not create samba server dir '%s'", s->smb_dir);
1.1 root 496: return -1;
497: }
498: snprintf(smb_conf, sizeof(smb_conf), "%s/%s", s->smb_dir, "smb.conf");
499:
500: f = fopen(smb_conf, "w");
501: if (!f) {
502: slirp_smb_cleanup(s);
1.1.1.3 root 503: error_report("could not create samba server configuration file '%s'",
504: smb_conf);
1.1 root 505: return -1;
506: }
507: fprintf(f,
508: "[global]\n"
509: "private dir=%s\n"
510: "smb ports=0\n"
511: "socket address=127.0.0.1\n"
512: "pid directory=%s\n"
513: "lock directory=%s\n"
514: "log file=%s/log.smbd\n"
515: "smb passwd file=%s/smbpasswd\n"
516: "security = share\n"
517: "[qemu]\n"
518: "path=%s\n"
519: "read only=no\n"
520: "guest ok=yes\n",
521: s->smb_dir,
522: s->smb_dir,
523: s->smb_dir,
524: s->smb_dir,
525: s->smb_dir,
526: exported_dir
527: );
528: fclose(f);
529:
530: snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
1.1.1.4 root 531: CONFIG_SMBD_COMMAND, smb_conf);
1.1 root 532:
533: if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0) {
534: slirp_smb_cleanup(s);
1.1.1.3 root 535: error_report("conflicting/invalid smbserver address");
1.1 root 536: return -1;
537: }
538: return 0;
539: }
540:
541: /* automatic user mode samba server configuration (legacy interface) */
542: int net_slirp_smb(const char *exported_dir)
543: {
544: struct in_addr vserver_addr = { .s_addr = 0 };
545:
546: if (legacy_smb_export) {
547: fprintf(stderr, "-smb given twice\n");
548: return -1;
549: }
550: legacy_smb_export = exported_dir;
551: if (!QTAILQ_EMPTY(&slirp_stacks)) {
552: return slirp_smb(QTAILQ_FIRST(&slirp_stacks), exported_dir,
553: vserver_addr);
554: }
555: return 0;
556: }
557:
558: #endif /* !defined(_WIN32) */
559:
560: struct GuestFwd {
561: CharDriverState *hd;
562: struct in_addr server;
563: int port;
564: Slirp *slirp;
565: };
566:
567: static int guestfwd_can_read(void *opaque)
568: {
569: struct GuestFwd *fwd = opaque;
570: return slirp_socket_can_recv(fwd->slirp, fwd->server, fwd->port);
571: }
572:
573: static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
574: {
575: struct GuestFwd *fwd = opaque;
576: slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
577: }
578:
579: static int slirp_guestfwd(SlirpState *s, const char *config_str,
580: int legacy_format)
581: {
582: struct in_addr server = { .s_addr = 0 };
583: struct GuestFwd *fwd;
584: const char *p;
585: char buf[128];
586: char *end;
587: int port;
588:
589: p = config_str;
590: if (legacy_format) {
591: if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
592: goto fail_syntax;
593: }
594: } else {
595: if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
596: goto fail_syntax;
597: }
598: if (strcmp(buf, "tcp") && buf[0] != '\0') {
599: goto fail_syntax;
600: }
601: if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
602: goto fail_syntax;
603: }
604: if (buf[0] != '\0' && !inet_aton(buf, &server)) {
605: goto fail_syntax;
606: }
607: if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
608: goto fail_syntax;
609: }
610: }
611: port = strtol(buf, &end, 10);
612: if (*end != '\0' || port < 1 || port > 65535) {
613: goto fail_syntax;
614: }
615:
1.1.1.5 ! root 616: fwd = g_malloc(sizeof(struct GuestFwd));
1.1.1.4 root 617: snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
1.1.1.5 ! root 618: fwd->hd = qemu_chr_new(buf, p, NULL);
1.1 root 619: if (!fwd->hd) {
1.1.1.3 root 620: error_report("could not open guest forwarding device '%s'", buf);
1.1.1.5 ! root 621: g_free(fwd);
1.1 root 622: return -1;
623: }
624:
625: if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) {
1.1.1.3 root 626: error_report("conflicting/invalid host:port in guest forwarding "
627: "rule '%s'", config_str);
1.1.1.5 ! root 628: g_free(fwd);
1.1 root 629: return -1;
630: }
631: fwd->server = server;
632: fwd->port = port;
633: fwd->slirp = s->slirp;
634:
635: qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
636: NULL, fwd);
637: return 0;
638:
639: fail_syntax:
1.1.1.3 root 640: error_report("invalid guest forwarding rule '%s'", config_str);
1.1 root 641: return -1;
642: }
643:
644: void do_info_usernet(Monitor *mon)
645: {
646: SlirpState *s;
647:
648: QTAILQ_FOREACH(s, &slirp_stacks, entry) {
649: monitor_printf(mon, "VLAN %d (%s):\n",
650: s->nc.vlan ? s->nc.vlan->id : -1,
651: s->nc.name);
652: slirp_connection_info(s->slirp, mon);
653: }
654: }
655:
656: static int net_init_slirp_configs(const char *name, const char *value, void *opaque)
657: {
658: struct slirp_config_str *config;
659:
660: if (strcmp(name, "hostfwd") != 0 && strcmp(name, "guestfwd") != 0) {
661: return 0;
662: }
663:
1.1.1.5 ! root 664: config = g_malloc0(sizeof(*config));
1.1 root 665:
666: pstrcpy(config->str, sizeof(config->str), value);
667:
668: if (!strcmp(name, "hostfwd")) {
669: config->flags = SLIRP_CFG_HOSTFWD;
670: }
671:
672: config->next = slirp_configs;
673: slirp_configs = config;
674:
675: return 0;
676: }
677:
678: int net_init_slirp(QemuOpts *opts,
679: Monitor *mon,
680: const char *name,
681: VLANState *vlan)
682: {
683: struct slirp_config_str *config;
684: const char *vhost;
685: const char *vhostname;
686: const char *vdhcp_start;
687: const char *vnamesrv;
688: const char *tftp_export;
689: const char *bootfile;
690: const char *smb_export;
691: const char *vsmbsrv;
1.1.1.4 root 692: const char *restrict_opt;
1.1 root 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:
1.1.1.4 root 706: restrict_opt = qemu_opt_get(opts, "restrict");
707: if (restrict_opt) {
708: if (!strcmp(restrict_opt, "on") ||
709: !strcmp(restrict_opt, "yes") || !strcmp(restrict_opt, "y")) {
710: restricted = 1;
711: } else if (strcmp(restrict_opt, "off") &&
712: strcmp(restrict_opt, "no") && strcmp(restrict_opt, "n")) {
713: error_report("invalid option: 'restrict=%s'", restrict_opt);
714: return -1;
715: }
716: }
717:
1.1 root 718: if (qemu_opt_get(opts, "ip")) {
719: const char *ip = qemu_opt_get(opts, "ip");
720: int l = strlen(ip) + strlen("/24") + 1;
721:
1.1.1.5 ! root 722: vnet = g_malloc(l);
1.1 root 723:
724: /* emulate legacy ip= parameter */
725: pstrcpy(vnet, l, ip);
726: pstrcat(vnet, l, "/24");
727: }
728:
729: if (qemu_opt_get(opts, "net")) {
730: if (vnet) {
1.1.1.5 ! root 731: g_free(vnet);
1.1 root 732: }
1.1.1.5 ! root 733: vnet = g_strdup(qemu_opt_get(opts, "net"));
1.1 root 734: }
735:
736: qemu_opt_foreach(opts, net_init_slirp_configs, NULL, 0);
737:
738: ret = net_slirp_init(vlan, "user", name, restricted, vnet, vhost,
739: vhostname, tftp_export, bootfile, vdhcp_start,
740: vnamesrv, smb_export, vsmbsrv);
741:
742: while (slirp_configs) {
743: config = slirp_configs;
744: slirp_configs = config->next;
1.1.1.5 ! root 745: g_free(config);
1.1 root 746: }
747:
1.1.1.5 ! root 748: g_free(vnet);
1.1 root 749:
750: return ret;
751: }
752:
753: int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret)
754: {
755: if (strcmp(opts_list->name, "net") != 0 ||
756: strncmp(optarg, "channel,", strlen("channel,")) != 0) {
757: return 0;
758: }
759:
760: /* handle legacy -net channel,port:chr */
761: optarg += strlen("channel,");
762:
763: if (QTAILQ_EMPTY(&slirp_stacks)) {
764: struct slirp_config_str *config;
765:
1.1.1.5 ! root 766: config = g_malloc(sizeof(*config));
1.1 root 767: pstrcpy(config->str, sizeof(config->str), optarg);
768: config->flags = SLIRP_CFG_LEGACY;
769: config->next = slirp_configs;
770: slirp_configs = config;
771: *ret = 0;
772: } else {
773: *ret = slirp_guestfwd(QTAILQ_FIRST(&slirp_stacks), optarg, 1);
774: }
775:
776: return 1;
777: }
778:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.