From: Anthony Liguori <anthony@codemonkey.ws>
To: qemu-devel@nongnu.org
Cc: Erwan Velu <erwan.velu@free.fr>
Subject: Re: [Qemu-devel] [PATCH 1/1] Making pxe working in the "NAT" mode
Date: Thu, 15 Feb 2007 21:49:13 -0600 [thread overview]
Message-ID: <45D529B9.5020001@codemonkey.ws> (raw)
In-Reply-To: <45D38A2C.1060101@free.fr>
[-- Attachment #1: Type: text/plain, Size: 2999 bytes --]
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
>
[-- Attachment #2: slirp-bootp.diff --]
[-- Type: text/x-patch, Size: 2981 bytes --]
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
[-- Attachment #3: slirp-tftp-oack.diff --]
[-- Type: text/x-patch, Size: 2781 bytes --]
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
[-- Attachment #4: tftp-root.diff --]
[-- Type: text/x-patch, Size: 2500 bytes --]
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"
next prev parent reply other threads:[~2007-02-16 3:49 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-14 22:16 [Qemu-devel] [PATCH 1/1] Making pxe working in the "NAT" mode Erwan Velu
2007-02-16 3:49 ` Anthony Liguori [this message]
2007-02-16 10:12 ` Erwan Velu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=45D529B9.5020001@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=erwan.velu@free.fr \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.