Currently the user-level networking (slirp) code in qemu uses subnet 10.0.2.0/24. Changing this hardcoded value, which can be desirable if that subnet is already used for other purposes, requires recompiling qemu.
The attached patch makes the subnet configurable on the command line via a new "subnet" option to "-net user". The subnet must be specified as "X.X.X.X/24". This change also affected the handling of "-redir", since qemu uses X.X.X.15 as the target address if the user does not specify one. Since qemu parses command-line options immediately but defers acting on "-net" options, net_slirp_redir() wouldn't know what subnet to use. It seems that "-redir", "-smb" and "-tftp", which are all slirp-specific, logically belong under "-net user" anyway, so I converted them into "-net user" options. Doing so cleans up the code quite a bit, as slirp gets initialized only by net_client_init(). Finally, the patch includes the "hostname" option to "-net user", which I posted in a previous patch. Comments and suggestions would be welcome. --Ed
diff -BurN -x '*.orig' -x '*~' qemu-snapshot-2006-03-27_23.orig/slirp/bootp.c qemu-snapshot-2006-03-27_23/slirp/bootp.c --- qemu-snapshot-2006-03-27_23.orig/slirp/bootp.c 2005-06-05 17:11:42.000000000 +0000 +++ qemu-snapshot-2006-03-27_23/slirp/bootp.c 2006-04-10 23:26:49.000000000 +0000 @@ -27,8 +27,6 @@ #define NB_ADDR 16 -#define START_ADDR 15 - #define LEASE_TIME (24 * 3600) typedef struct { @@ -47,6 +45,8 @@ #define dprintf(fmt, args...) #endif +const char *dhcp_hostname; + static BOOTPClient *get_new_addr(struct in_addr *paddr) { BOOTPClient *bc; @@ -60,7 +60,7 @@ found: bc = &bootp_clients[i]; bc->allocated = 1; - paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); + paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + DHCP_START_ADDR)); return bc; } @@ -77,7 +77,7 @@ found: bc = &bootp_clients[i]; bc->allocated = 1; - paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); + paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + DHCP_START_ADDR)); return bc; } @@ -228,6 +228,16 @@ val = htonl(LEASE_TIME); memcpy(q, &val, 4); q += 4; + + if (dhcp_hostname && *dhcp_hostname) { + val = strlen(dhcp_hostname); + if (val > 32) + val = 32; + *q++ = RFC1533_HOSTNAME; + *q++ = val; + memcpy(q, dhcp_hostname, val); + q += val; + } } *q++ = RFC1533_END; diff -BurN -x '*.orig' -x '*~' qemu-snapshot-2006-03-27_23.orig/slirp/ctl.h qemu-snapshot-2006-03-27_23/slirp/ctl.h --- qemu-snapshot-2006-03-27_23.orig/slirp/ctl.h 2004-04-22 00:10:47.000000000 +0000 +++ qemu-snapshot-2006-03-27_23/slirp/ctl.h 2006-04-10 23:26:49.000000000 +0000 @@ -2,6 +2,3 @@ #define CTL_EXEC 1 #define CTL_ALIAS 2 #define CTL_DNS 3 - -#define CTL_SPECIAL "10.0.2.0" -#define CTL_LOCAL "10.0.2.15" diff -BurN -x '*.orig' -x '*~' qemu-snapshot-2006-03-27_23.orig/slirp/libslirp.h qemu-snapshot-2006-03-27_23/slirp/libslirp.h --- qemu-snapshot-2006-03-27_23.orig/slirp/libslirp.h 2005-06-05 17:11:42.000000000 +0000 +++ qemu-snapshot-2006-03-27_23/slirp/libslirp.h 2006-04-10 23:26:49.000000000 +0000 @@ -13,7 +13,7 @@ extern "C" { #endif -void slirp_init(void); +void slirp_init(struct in_addr subnet, char *dhcp_host, char *tftp_pfx); void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds); @@ -31,8 +31,6 @@ int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, int guest_port); -extern const char *tftp_prefix; - #ifdef __cplusplus } #endif diff -BurN -x '*.orig' -x '*~' qemu-snapshot-2006-03-27_23.orig/slirp/slirp.c qemu-snapshot-2006-03-27_23/slirp/slirp.c --- qemu-snapshot-2006-03-27_23.orig/slirp/slirp.c 2006-04-10 23:23:29.000000000 +0000 +++ qemu-snapshot-2006-03-27_23/slirp/slirp.c 2006-04-10 23:26:49.000000000 +0000 @@ -123,7 +123,7 @@ } #endif -void slirp_init(void) +void slirp_init(struct in_addr subnet, char *dhcp_host, char *tftp_pfx) { // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); @@ -151,8 +151,13 @@ exit(1); } - inet_aton(CTL_SPECIAL, &special_addr); + special_addr = subnet; getouraddr(); + + if (dhcp_host) + dhcp_hostname = dhcp_host; + if (tftp_pfx) + tftp_prefix = tftp_pfx; } #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) @@ -639,6 +644,8 @@ int slirp_redir(int is_udp, int host_port, struct in_addr guest_addr, int guest_port) { + if (!guest_addr.s_addr) + guest_addr.s_addr = htonl(ntohl(special_addr.s_addr) | DHCP_START_ADDR); if (is_udp) { if (!udp_listen(htons(host_port), guest_addr.s_addr, htons(guest_port), 0)) diff -BurN -x '*.orig' -x '*~' qemu-snapshot-2006-03-27_23.orig/slirp/slirp.h qemu-snapshot-2006-03-27_23/slirp/slirp.h --- qemu-snapshot-2006-03-27_23.orig/slirp/slirp.h 2005-01-10 23:19:34.000000000 +0000 +++ qemu-snapshot-2006-03-27_23/slirp/slirp.h 2006-04-10 23:26:49.000000000 +0000 @@ -336,4 +336,9 @@ #define errno (WSAGetLastError()) #endif +extern const char *dhcp_hostname; +extern const char *tftp_prefix; + +#define DHCP_START_ADDR 15 + #endif diff -BurN -x '*.orig' -x '*~' qemu-snapshot-2006-03-27_23.orig/vl.c qemu-snapshot-2006-03-27_23/vl.c --- qemu-snapshot-2006-03-27_23.orig/vl.c 2006-04-10 23:23:29.000000000 +0000 +++ qemu-snapshot-2006-03-27_23/vl.c 2006-04-10 23:27:37.000000000 +0000 @@ -1965,15 +1965,16 @@ slirp_input(buf, size); } -static int net_slirp_init(VLANState *vlan) +static int net_slirp_init(VLANState *vlan, struct in_addr subnet, char *dhcp_host, + char *tftp_pfx) { - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } + if (slirp_inited) + return -1; + slirp_init(subnet, strdup(dhcp_host), strdup(tftp_pfx)); slirp_vc = qemu_new_vlan_client(vlan, slirp_receive, NULL, NULL); snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector"); + slirp_inited = 1; return 0; } @@ -1985,11 +1986,6 @@ struct in_addr guest_addr; int host_port, guest_port; - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } - p = redir_str; if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) goto fail; @@ -2010,9 +2006,8 @@ if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) goto fail; if (buf[0] == '\0') { - pstrcpy(buf, sizeof(buf), "10.0.2.15"); - } - if (!inet_aton(buf, &guest_addr)) + guest_addr.s_addr = 0; + } else if (!inet_aton(buf, &guest_addr)) goto fail; guest_port = strtol(p, &r, 0); @@ -2025,7 +2020,7 @@ } return; fail: - fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n"); + fprintf(stderr, "qemu: syntax: redir=[tcp|udp]:host-port:[guest-host]:guest-port[;...]\n"); exit(1); } @@ -2063,11 +2058,6 @@ char smb_cmdline[1024]; FILE *f; - if (!slirp_inited) { - slirp_inited = 1; - slirp_init(); - } - /* XXX: better tmp dir construction */ snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid()); if (mkdir(smb_dir, 0700) < 0) { @@ -2802,7 +2792,46 @@ } else #ifdef CONFIG_SLIRP if (!strcmp(device, "user")) { - ret = net_slirp_init(vlan); + struct in_addr subnet; + char dhcp_host[64]; + char tftp_pfx[1024]; + + if (get_param_value(buf, sizeof(buf), "subnet", p)) { + char * len = strchr( buf, 0 ) - 3; + if( len < buf || strcmp( len, "/24" )) { + fprintf(stderr, "qemu: invalid subnet=%s (I only deal with /24's)\n", buf ); + return -1; + } + *len = 0; + } else { + strcpy(buf, "10.0.2.0"); + } + if (!inet_aton(buf, &subnet)) { + fprintf(stderr, "qemu: invalid subnet=%s\n", buf ); + return -1; + } + if (!get_param_value(dhcp_host, sizeof(dhcp_host), "hostname", p)) + dhcp_host[0] = '\0'; + if (!get_param_value(tftp_pfx, sizeof(tftp_pfx), "tftp", p)) { + tftp_pfx[0] = '\0'; + } + if (net_slirp_init(vlan, subnet, dhcp_host, tftp_pfx) < 0) { + fprintf(stderr, "qemu: only one -net user instance allowed\n"); + return -1; + } + + if (get_param_value(buf, sizeof(buf), "redir", p)) { + char pbuf[1024]; + q = buf; + while (!get_str_sep(pbuf, sizeof(pbuf), &q, ";")) + net_slirp_redir(pbuf); + net_slirp_redir(q); + } +#ifndef _WIN32 + if (get_param_value(buf, sizeof(buf), "smb", p)) { + net_slirp_smb(buf); + } +#endif } else #endif #ifdef _WIN32 @@ -4202,8 +4223,15 @@ "-net nic[,vlan=n][,macaddr=addr][,model=type]\n" " create a new Network Interface Card and connect it to VLAN 'n'\n" #ifdef CONFIG_SLIRP - "-net user[,vlan=n]\n" - " connect the user mode network stack to VLAN 'n'\n" + "-net user[,vlan=n][,hostname=host][,subnet=addr][,tftp=prefix]\n" + " [,redir=[tcp|udp]:host-port:[guest-host]:guest-port[;...]\n" +#ifndef _WIN32 + " [,smb=dir]\n" +#endif + " connect the user mode network stack to VLAN 'n'; assign\n" + " hostname host to DHCP clients; use subnet addr (/24);\n" + " redirect TCP or UDP port from host to guest; allow tftp\n" + " access to files in prefix; allow SMB access to files in dir\n" #endif #ifdef _WIN32 "-net tap[,vlan=n],ifname=name\n" @@ -4221,15 +4249,6 @@ "-net none use it alone to have zero network devices; if no -net option\n" " is provided, the default is '-net nic -net user'\n" "\n" -#ifdef CONFIG_SLIRP - "-tftp prefix allow tftp access to files starting with prefix [-net user]\n" -#ifndef _WIN32 - "-smb dir allow SMB access to files in 'dir' [-net user]\n" -#endif - "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" - " redirect TCP or UDP connections from host to guest [-net user]\n" -#endif - "\n" "Linux boot specific:\n" "-kernel bzImage use 'bzImage' as kernel image\n" "-append cmdline use 'cmdline' as kernel command line\n" @@ -4310,9 +4329,6 @@ #endif QEMU_OPTION_net, - QEMU_OPTION_tftp, - QEMU_OPTION_smb, - QEMU_OPTION_redir, QEMU_OPTION_kernel, QEMU_OPTION_append, @@ -4373,13 +4389,6 @@ #endif { "net", HAS_ARG, QEMU_OPTION_net}, -#ifdef CONFIG_SLIRP - { "tftp", HAS_ARG, QEMU_OPTION_tftp }, -#ifndef _WIN32 - { "smb", HAS_ARG, QEMU_OPTION_smb }, -#endif - { "redir", HAS_ARG, QEMU_OPTION_redir }, -#endif { "kernel", HAS_ARG, QEMU_OPTION_kernel }, { "append", HAS_ARG, QEMU_OPTION_append }, @@ -4831,19 +4840,6 @@ optarg); nb_net_clients++; break; -#ifdef CONFIG_SLIRP - case QEMU_OPTION_tftp: - tftp_prefix = optarg; - break; -#ifndef _WIN32 - case QEMU_OPTION_smb: - net_slirp_smb(optarg); - break; -#endif - case QEMU_OPTION_redir: - net_slirp_redir(optarg); - break; -#endif #ifdef HAS_AUDIO case QEMU_OPTION_audio_help: AUD_help ();
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel