qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/1] Making pxe working in the "NAT" mode
@ 2007-02-14 22:16 Erwan Velu
  2007-02-16  3:49 ` Anthony Liguori
  0 siblings, 1 reply; 3+ messages in thread
From: Erwan Velu @ 2007-02-14 22:16 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1942 bytes --]

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.

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.

[-- Attachment #2: pxe-qemu.patch --]
[-- Type: text/x-patch, Size: 5242 bytes --]

diff -rub slirp.old/bootp.c slirp/bootp.c
--- slirp.old/bootp.c	2007-02-06 00:01:54.000000000 +0100
+++ slirp/bootp.c	2007-02-14 22:44:02.000000000 +0100
@@ -82,7 +82,7 @@
 }
 
 static void dhcp_decode(const uint8_t *buf, int size,
-                        int *pmsg_type)
+                        int *pmsg_type, int *pxe_request)
 {
     const uint8_t *p, *p_end;
     int len, tag;
@@ -114,6 +114,11 @@
                 if (len >= 1)
                     *pmsg_type = p[0];
                 break;
+            case RFC1533_CLASSIDENTIFIER:
+	        if ((strncmp(p,"PXEClient",9) == 0) || (strncmp(p,"Etherboot",9) == 0)) {
+		     *pxe_request=1;
+		}
+		break;
             default:
                 break;
             }
@@ -131,9 +136,10 @@
     struct in_addr dns_addr;
     int dhcp_msg_type, val;
     uint8_t *q;
+    int pxe_request=0;
 
     /* extract exact DHCP msg type */
-    dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
+    dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type,&pxe_request);
     dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
     
     if (dhcp_msg_type == 0)
@@ -168,6 +174,12 @@
             goto new_addr;
         }
     }
+
+    if (pxe_request==1) {
+           printf("PXE Request Detected, setting filename\n");
+           strcpy(rbp->bp_file,"/pxelinux.0");
+    }
+
     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 -rub slirp.old/bootp.h slirp/bootp.h
--- slirp.old/bootp.h	2007-02-06 00:01:54.000000000 +0100
+++ slirp/bootp.h	2007-02-14 22:12:48.000000000 +0100
@@ -57,6 +57,7 @@
 #define RFC1533_NBSCOPE		47
 #define RFC1533_XFS		48
 #define RFC1533_XDM		49
+#define RFC1533_CLASSIDENTIFIER 60
 
 #define RFC2132_REQ_ADDR	50
 #define RFC2132_LEASE_TIME      51
Seulement dans slirp: bootp.h~
Seulement dans slirp: debug.c~
diff -rub slirp.old/tftp.c slirp/tftp.c
--- slirp.old/tftp.c	2007-02-06 00:01:54.000000000 +0100
+++ slirp/tftp.c	2007-02-14 22:09:16.000000000 +0100
@@ -120,6 +120,49 @@
   return bytes_read;
 }
 
+static int tftp_send_oack(struct tftp_session *spt, 
+                          int errorcode, const char *msg,
+                          struct tftp_t *recv_tp)
+{
+  struct sockaddr_in saddr, daddr;
+  struct mbuf *m;
+  struct tftp_t *tp;
+  int nobytes;
+  char errcode[16];
+  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);
+  strcpy(tp->x.tp_buf,msg);
+  sprintf(tp->x.tp_buf+strlen(msg)+1,"%u",errorcode);
+  sprintf(errcode,"%u",errorcode);
+
+  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;
+
+  nobytes = 2;
+
+  m->m_len = sizeof(struct tftp_t) - 514 + 2 + strlen(errcode) + strlen(msg) - 
+        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)
@@ -227,8 +270,12 @@
 static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 {
   struct tftp_session *spt;
-  int s, k, n;
+  int s, k, n, blksize,tsize;
   u_int8_t *src, *dst;
+  char *blksize_pos, *tsize_pos;
+
+  char tftp_path[TFTP_FILENAME_MAX];
+  struct stat stat_p; 
 
   s = tftp_session_allocate(tp);
 
@@ -261,6 +308,9 @@
     return;
   }
   
+  snprintf(tftp_path,TFTP_FILENAME_MAX, "%s%s%s",getenv("HOME"),"/tftpboot", spt->filename);
+  strncpy((char *)spt->filename,tftp_path,TFTP_FILENAME_MAX);
+  
   k++;
   
   /* check mode */
@@ -273,6 +323,34 @@
       return;
   }
 
+ k+=6;/* skipping octet*/
+
+ /* Looking for other options*/ 
+ while (k<n) {
+   blksize_pos=strstr(&src[k],"blksize");
+   if (blksize_pos != NULL) {
+       blksize=atoi(blksize_pos+strlen("blksize")+1);
+       k+=strlen("blksize")+strlen(blksize_pos+strlen("blksize")+1);
+   }
+
+   tsize_pos=strstr(&src[k],"tsize");
+   if (tsize_pos != NULL) {
+       tsize=atoi(tsize_pos+strlen("tsize")+1);
+       if (tsize==0) {
+                /* we need to return the file size to the client*/
+                if ( stat (spt->filename, &stat_p) == 0 ) {
+                       tsize=stat_p.st_size;
+                } else  {
+                       tftp_send_error(spt, 1, "File not found", tp);
+                }
+       }
+       tftp_send_oack(spt,tsize,"tsize",tp);
+       k+=strlen("tsize")+strlen(tsize_pos+strlen("tsize")+1);
+   }
+ k++;
+ }
+
+#if 0
   /* do sanity checks on the filename */
 
   if ((spt->filename[0] != '/')
@@ -289,6 +367,7 @@
       tftp_send_error(spt, 2, "Access violation", tp);
       return;
   }
+#endif
 
   /* check if the file exists */
   
diff -rub slirp.old/tftp.h slirp/tftp.h
--- slirp.old/tftp.h	2007-02-06 00:01:54.000000000 +0100
+++ slirp/tftp.h	2007-02-14 22:09:36.000000000 +0100
@@ -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
 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-02-16 10:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2007-02-16 10:12   ` Erwan Velu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).