From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1HHu62-0004am-O0 for qemu-devel@nongnu.org; Thu, 15 Feb 2007 22:49:18 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1HHu62-0004aa-1L for qemu-devel@nongnu.org; Thu, 15 Feb 2007 22:49:18 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1HHu61-0004aX-QR for qemu-devel@nongnu.org; Thu, 15 Feb 2007 22:49:17 -0500 Received: from nz-out-0506.google.com ([64.233.162.238]) by monty-python.gnu.org with esmtp (Exim 4.52) id 1HHu61-0000bZ-CG for qemu-devel@nongnu.org; Thu, 15 Feb 2007 22:49:17 -0500 Received: by nz-out-0506.google.com with SMTP id i11so1323442nzi for ; Thu, 15 Feb 2007 19:49:16 -0800 (PST) Message-ID: <45D529B9.5020001@codemonkey.ws> Date: Thu, 15 Feb 2007 21:49:13 -0600 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH 1/1] Making pxe working in the "NAT" mode References: <45D38A2C.1060101@free.fr> In-Reply-To: <45D38A2C.1060101@free.fr> Content-Type: multipart/mixed; boundary="------------050604000201030509000809" Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Erwan Velu This is a multi-part message in MIME format. --------------050604000201030509000809 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Erwan Velu wrote: > Hey folks, > I saw the lastest qemu support pxe so I tried it using the following > command: > > qemu -hda /tmp/a.img -net nic n- user -boot n > > Note that now qemu support pxe mode, the mandatory -hda option is no > more mandatory but this is not directly linked to my patch. > I saw qemu integrates a dhcp & a tftp server but they don't seems to > be configured/developped for a pxe boot process. > Qemu says "no filename" and exits. Hi Erwan, I really like the idea of your patch. Of course, the hard coding is not really reasonable :-) Also, PXE is an x86-ism. What you've really done is added a mechanism to publish a BOOTP name. We do need to add a new option too as one may want to use -boot n without publishing a BOOTP filename. Using your patch as a basis, I've written three patches. The first one is the tsize negotiation fix for the TFTP server. The second adds a -bootp option for specifying the location of the BOOTP image. The third changes the -tftp option to take root directory. The end result, is that now you can say: qemu -hda /tmp/a.img -boot n -tftp ~/tftpboot -bootp /pxelinux.0 And you get the same results without the hard coding. What do you think? Regards, Anthony Liguori > A friend of I asked me "how do you boot using pxe in qemu when you > don't have a dhcp & a tftp server ?". > So I started to look how we can do that, I modified bootp to catch the > field 60 of a dhcp request to find if its a pxe request or not. > If yes, I set the filename to "/pxelinux.0", currently this is > harcoded, maybe you can help me to find a better way to specify a > bootloader. > > Then, I've patched the tftp server to change the default rootdir in my > home dir. "~/tftpboot". This is just for a Proof-of-concept, other > methods could be fine. We can also imagine searching in a path > restricted to the admin and then in the user dir. So it can give the > admin the ability of defining some pxe boot for all the vm of a > system or in the user dir if the user wants to have a special pxe > boot scheme. > > The last patch I did on the tftp server, is to allow the tsize > negociation because pxelinux needs it. > > This patch apply to 0.9.0, once it is applied and compiled here come > the test procedure: > > create a ~/tftpboot/pxelinux.cfg directory > copy pxelinux.0 in ~/tfptboot/ > create a pxelinux configuration file called "default" in > ~/tftpboot/pxelinux.cfg > > Et voila ;) > > Just call "qemu -hda /tmp/a.img -net nic n- user -boot n", it will > start pxelinux. > > I think this patch is very usefull because it give users & admin the > ability to use pxe inside the VM without installing the full > configuration (dhcp,tftp). > This patch is mainly a proof-of-concept, this patch can be improved, > comments and feedback are welcome. > _______________________________________________ > Qemu-devel mailing list > Qemu-devel@nongnu.org > http://lists.nongnu.org/mailman/listinfo/qemu-devel > --------------050604000201030509000809 Content-Type: text/x-patch; name="slirp-bootp.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="slirp-bootp.diff" diff -r ea5eb79ade8d slirp/bootp.c --- a/slirp/bootp.c Thu Feb 15 16:49:28 2007 -0600 +++ b/slirp/bootp.c Thu Feb 15 16:49:30 2007 -0600 @@ -38,6 +38,8 @@ typedef struct { BOOTPClient bootp_clients[NB_ADDR]; +const char *bootp_filename; + static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; #ifdef DEBUG @@ -168,6 +170,10 @@ static void bootp_reply(struct bootp_t * goto new_addr; } } + + if (bootp_filename) + snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename); + dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr)); saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); diff -r ea5eb79ade8d vl.c --- a/vl.c Thu Feb 15 16:49:28 2007 -0600 +++ b/vl.c Thu Feb 15 16:57:07 2007 -0600 @@ -6488,6 +6488,7 @@ void help(void) "\n" #ifdef CONFIG_SLIRP "-tftp prefix allow tftp access to files starting with prefix [-net user]\n" + "-bootp file advertise file in BOOTP replies\n" #ifndef _WIN32 "-smb dir allow SMB access to files in 'dir' [-net user]\n" #endif @@ -6576,6 +6577,7 @@ enum { QEMU_OPTION_net, QEMU_OPTION_tftp, + QEMU_OPTION_bootp, QEMU_OPTION_smb, QEMU_OPTION_redir, @@ -6652,6 +6654,7 @@ const QEMUOption qemu_options[] = { { "net", HAS_ARG, QEMU_OPTION_net}, #ifdef CONFIG_SLIRP { "tftp", HAS_ARG, QEMU_OPTION_tftp }, + { "bootp", HAS_ARG, QEMU_OPTION_bootp }, #ifndef _WIN32 { "smb", HAS_ARG, QEMU_OPTION_smb }, #endif @@ -7185,6 +7188,9 @@ int main(int argc, char **argv) case QEMU_OPTION_tftp: tftp_prefix = optarg; break; + case QEMU_OPTION_bootp: + bootp_filename = optarg; + break; #ifndef _WIN32 case QEMU_OPTION_smb: net_slirp_smb(optarg); diff -r ea5eb79ade8d vl.h --- a/vl.h Thu Feb 15 16:49:28 2007 -0600 +++ b/vl.h Thu Feb 15 16:49:30 2007 -0600 @@ -163,6 +163,7 @@ extern int no_quit; extern int no_quit; extern int semihosting_enabled; extern int autostart; +extern const char *bootp_filename; #define MAX_OPTION_ROMS 16 extern const char *option_rom[MAX_OPTION_ROMS]; diff -r ea5eb79ade8d qemu-doc.texi --- a/qemu-doc.texi Thu Feb 15 16:49:28 2007 -0600 +++ b/qemu-doc.texi Thu Feb 15 16:57:23 2007 -0600 @@ -445,6 +445,16 @@ guest must be configured in binary mode guest must be configured in binary mode (use the command @code{bin} of the Unix TFTP client). The host IP address on the guest is as usual 10.0.2.2. + +@item -bootp file +When using the user mode network stack, broadcast @var{file} as the BOOTP +filename. In conjunction with @option{-tftp}, this can be used to network boot +a guest from a local directory. + +Example (using pxelinux): +@example +qemu -hda linux.img -boot n -tftp /path/to/tftp/files -bootp /pxelinux.0 +@end example @item -smb dir When using the user mode network stack, activate a built-in SMB --------------050604000201030509000809 Content-Type: text/x-patch; name="slirp-tftp-oack.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="slirp-tftp-oack.diff" diff -r 153828edbad3 slirp/tftp.c --- a/slirp/tftp.c Thu Feb 15 16:37:56 2007 -0600 +++ b/slirp/tftp.c Thu Feb 15 21:37:26 2007 -0600 @@ -120,6 +120,45 @@ static int tftp_read_data(struct tftp_se return bytes_read; } +static int tftp_send_oack(struct tftp_session *spt, + const char *key, uint32_t value, + struct tftp_t *recv_tp) +{ + struct sockaddr_in saddr, daddr; + struct mbuf *m; + struct tftp_t *tp; + int n = 0; + + m = m_get(); + + if (!m) + return -1; + + memset(m->m_data, 0, m->m_size); + + m->m_data += if_maxlinkhdr; + tp = (void *)m->m_data; + m->m_data += sizeof(struct udpiphdr); + + tp->tp_op = htons(TFTP_OACK); + n += sprintf(tp->x.tp_buf + n, "%s", key) + 1; + n += sprintf(tp->x.tp_buf + n, "%u", value) + 1; + + saddr.sin_addr = recv_tp->ip.ip_dst; + saddr.sin_port = recv_tp->udp.uh_dport; + + daddr.sin_addr = spt->client_ip; + daddr.sin_port = spt->client_port; + + m->m_len = sizeof(struct tftp_t) - 514 + n - + sizeof(struct ip) - sizeof(struct udphdr); + udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + + return 0; +} + + + static int tftp_send_error(struct tftp_session *spt, u_int16_t errorcode, const char *msg, struct tftp_t *recv_tp) @@ -273,6 +312,8 @@ static void tftp_handle_rrq(struct tftp_ return; } + k += 6;/* skipping octet*/ + /* do sanity checks on the filename */ if ((spt->filename[0] != '/') @@ -297,6 +338,48 @@ static void tftp_handle_rrq(struct tftp_ return; } + if (src[n - 1] != 0) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } + + while (k < n) { + const char *key, *value; + + key = src + k; + k += strlen(key) + 1; + + if (k >= n) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } + + value = src + k; + k += strlen(value) + 1; + + if (strcmp(key, "tsize") == 0) { + int tsize = atoi(value); + struct stat stat_p; + + if (tsize == 0 && tftp_prefix) { + char buffer[1024]; + int len; + + len = snprintf(buffer, sizeof(buffer), "%s/%s", + tftp_prefix, spt->filename); + + if (stat(buffer, &stat_p) == 0) + tsize = stat_p.st_size; + else { + tftp_send_error(spt, 1, "File not found", tp); + return; + } + } + + tftp_send_oack(spt, "tsize", tsize, tp); + } + } + tftp_send_data(spt, 1, tp); } diff -r 153828edbad3 slirp/tftp.h --- a/slirp/tftp.h Thu Feb 15 16:37:56 2007 -0600 +++ b/slirp/tftp.h Thu Feb 15 16:37:57 2007 -0600 @@ -9,6 +9,7 @@ #define TFTP_DATA 3 #define TFTP_ACK 4 #define TFTP_ERROR 5 +#define TFTP_OACK 6 #define TFTP_FILENAME_MAX 512 --------------050604000201030509000809 Content-Type: text/x-patch; name="tftp-root.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="tftp-root.diff" diff -r 91f98dfbdc3f qemu-doc.texi --- a/qemu-doc.texi Thu Feb 15 21:22:02 2007 -0600 +++ b/qemu-doc.texi Thu Feb 15 21:22:03 2007 -0600 @@ -438,13 +438,12 @@ override the default configuration (@opt override the default configuration (@option{-net nic -net user}) which is activated if no @option{-net} options are provided. -@item -tftp prefix +@item -tftp dir When using the user mode network stack, activate a built-in TFTP -server. All filenames beginning with @var{prefix} can be downloaded -from the host to the guest using a TFTP client. The TFTP client on the -guest must be configured in binary mode (use the command @code{bin} of -the Unix TFTP client). The host IP address on the guest is as usual -10.0.2.2. +server. The files in @var{dir} will be exposed as the root of a TFTP server. +The TFTP client on the guest must be configured in binary mode (use the command +@code{bin} of the Unix TFTP client). The host IP address on the guest is as +usual 10.0.2.2. @item -bootp file When using the user mode network stack, broadcast @var{file} as the BOOTP diff -r 91f98dfbdc3f slirp/tftp.c --- a/slirp/tftp.c Thu Feb 15 21:22:02 2007 -0600 +++ b/slirp/tftp.c Thu Feb 15 21:22:03 2007 -0600 @@ -102,8 +102,15 @@ static int tftp_read_data(struct tftp_se { int fd; int bytes_read = 0; - - fd = open(spt->filename, O_RDONLY | O_BINARY); + char buffer[1024]; + int n; + + n = snprintf(buffer, sizeof(buffer), "%s/%s", + tftp_prefix, spt->filename); + if (n >= sizeof(buffer)) + return -1; + + fd = open(buffer, O_RDONLY | O_BINARY); if (fd < 0) { return -1; @@ -328,8 +335,7 @@ static void tftp_handle_rrq(struct tftp_ /* only allow exported prefixes */ - if (!tftp_prefix - || (strncmp(spt->filename, tftp_prefix, strlen(tftp_prefix)) != 0)) { + if (!tftp_prefix) { tftp_send_error(spt, 2, "Access violation", tp); return; } diff -r 91f98dfbdc3f vl.c --- a/vl.c Thu Feb 15 21:22:02 2007 -0600 +++ b/vl.c Thu Feb 15 21:22:03 2007 -0600 @@ -6487,7 +6487,7 @@ void help(void) " 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" + "-tftp dir allow tftp access to files in dir [-net user]\n" "-bootp file advertise file in BOOTP replies\n" #ifndef _WIN32 "-smb dir allow SMB access to files in 'dir' [-net user]\n" --------------050604000201030509000809--