All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel][PATCH] Built-in DHCP server
@ 2007-02-20  4:09 Kazu
  2007-02-20 14:22 ` Lonnie Mendez
  0 siblings, 1 reply; 3+ messages in thread
From: Kazu @ 2007-02-20  4:09 UTC (permalink / raw)
  To: qemu-devel

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

Hi,

After I used TAP device by -net nic -net tap,ifname=mytap and I tried to use
user mode network by -net nic -net user, a Windows XP guest doesn't get
IP address from a built-in DHCP server.

It is fixed by an attached patch.

DHCPRELEASE and DHCPNACK are introduced.

DHCPRELEASE code is borrowed from VirtualBox. Windows 2000/XP tries to call
DHCPREQUEST and get old IP address when it boots. I made a code to reply
DHCPNACK to the request. Then the Win2k/XP called DHCPDISCOVER and try to
get a new IP address.

I tested Windows 98SE/2000/XP, Knoppix 3.8, Morphix, Fedora Core 3 and
RedHat 7.2 guest.
There is not problem except RH7.2. It can get IP address but it is
10.0.2.16. dhcpcd in RH7.2 tries to call DHCPDISCOVER two times. So it
consumes two entries in the built-in DHCP server. It seems that it is a bug
of dhcpcd in RH7.2.

Regards,
Kazu

[-- Attachment #2: qemu-20070220-dhcp.patch --]
[-- Type: application/octet-stream, Size: 4066 bytes --]

Index: slirp/bootp.c
===================================================================
RCS file: /sources/qemu/qemu/slirp/bootp.c,v
retrieving revision 1.9
diff -u -r1.9 bootp.c
--- slirp/bootp.c	20 Feb 2007 00:05:08 -0000	1.9
+++ slirp/bootp.c	20 Feb 2007 03:36:39 -0000
@@ -66,6 +66,18 @@
     return bc;
 }
 
+/* From VirtualBox */
+static void release_addr(struct in_addr *paddr)
+{
+    int i;
+
+    i = ntohl(paddr->s_addr) - START_ADDR - ntohl(special_addr.s_addr);
+    if (i >= NB_ADDR)
+        return;
+    memset(bootp_clients[i].macaddr, '\0', 6);
+    bootp_clients[i].allocated = 0;
+}
+
 static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
 {
     BOOTPClient *bc;
@@ -133,6 +145,7 @@
     struct in_addr dns_addr;
     int dhcp_msg_type, val;
     uint8_t *q;
+    int freply_nack = 0;
 
     /* extract exact DHCP msg type */
     dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
@@ -141,6 +154,13 @@
     if (dhcp_msg_type == 0)
         dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
         
+    if (dhcp_msg_type == DHCPRELEASE) {
+        release_addr(&bp->bp_ciaddr);
+        dprintf("released addr=%08lx\n", ntohl(bp->bp_ciaddr.s_addr));
+        /* This message is not to be answered in any way. */
+        return;
+    }
+
     if (dhcp_msg_type != DHCPDISCOVER && 
         dhcp_msg_type != DHCPREQUEST)
         return;
@@ -155,7 +175,6 @@
     memset(rbp, 0, sizeof(struct bootp_t));
 
     if (dhcp_msg_type == DHCPDISCOVER) {
-    new_addr:
         bc = get_new_addr(&daddr.sin_addr);
         if (!bc) {
             dprintf("no address left\n");
@@ -165,16 +184,18 @@
     } else {
         bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
         if (!bc) {
-            /* if never assigned, behaves as if it was already
-               assigned (windows fix because it remembers its address) */
-            goto new_addr;
+            /* if never assigned, reply DHCPNACK to BROADCAST.
+               (windows fix because it remembers its address). */
+            daddr.sin_addr.s_addr = htonl(0xffffffff);
+            freply_nack = 1;
+            dprintf("reply NACK\n");
         }
     }
 
     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));
+    dprintf("offered addr=%08lx\n", ntohl(daddr.sin_addr.s_addr));
 
     saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
     saddr.sin_port = htons(BOOTP_SERVER);
@@ -187,7 +208,10 @@
     rbp->bp_hlen = 6;
     memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);
 
-    rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */
+    if (freply_nack)
+        rbp->bp_yiaddr.s_addr = htonl(0); /* When NACK, IP address is 0. */
+    else
+        rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */
     rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
 
     q = rbp->bp_vend;
@@ -201,11 +225,14 @@
     } else if (dhcp_msg_type == DHCPREQUEST) {
         *q++ = RFC2132_MSG_TYPE;
         *q++ = 1;
-        *q++ = DHCPACK;
+        if (freply_nack)
+            *q++ = DHCPNACK;
+        else
+            *q++ = DHCPACK;
     }
         
     if (dhcp_msg_type == DHCPDISCOVER ||
-        dhcp_msg_type == DHCPREQUEST) {
+        ((dhcp_msg_type == DHCPREQUEST) && !freply_nack)) {
         *q++ = RFC2132_SRV_ID;
         *q++ = 4;
         memcpy(q, &saddr.sin_addr, 4);
Index: slirp/bootp.h
===================================================================
RCS file: /sources/qemu/qemu/slirp/bootp.h,v
retrieving revision 1.2
diff -u -r1.2 bootp.h
--- slirp/bootp.h	5 Jun 2005 17:11:42 -0000	1.2
+++ slirp/bootp.h	20 Feb 2007 03:36:39 -0000
@@ -71,6 +71,8 @@
 #define DHCPOFFER		2
 #define DHCPREQUEST		3
 #define DHCPACK			5
+#define DHCPNACK		6
+#define DHCPRELEASE		7
 
 #define RFC1533_VENDOR_MAJOR	0
 #define RFC1533_VENDOR_MINOR	0

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

* Re: [Qemu-devel][PATCH] Built-in DHCP server
  2007-02-20  4:09 [Qemu-devel][PATCH] Built-in DHCP server Kazu
@ 2007-02-20 14:22 ` Lonnie Mendez
  2007-02-21  8:01   ` Kazu
  0 siblings, 1 reply; 3+ messages in thread
From: Lonnie Mendez @ 2007-02-20 14:22 UTC (permalink / raw)
  To: qemu-devel

On Tue, 2007-02-20 at 13:09 +0900, Kazu wrote:
> Hi,
> 
> After I used TAP device by -net nic -net tap,ifname=mytap and I tried to use
> user mode network by -net nic -net user, a Windows XP guest doesn't get
> IP address from a built-in DHCP server.
> 
> It is fixed by an attached patch.
> 
> DHCPRELEASE and DHCPNACK are introduced.
> 
> DHCPRELEASE code is borrowed from VirtualBox. Windows 2000/XP tries to call
> DHCPREQUEST and get old IP address when it boots. I made a code to reply
> DHCPNACK to the request. Then the Win2k/XP called DHCPDISCOVER and try to
> get a new IP address.
> 
> I tested Windows 98SE/2000/XP, Knoppix 3.8, Morphix, Fedora Core 3 and
> RedHat 7.2 guest.
> There is not problem except RH7.2. It can get IP address but it is
> 10.0.2.16. dhcpcd in RH7.2 tries to call DHCPDISCOVER two times. So it
> consumes two entries in the built-in DHCP server. It seems that it is a bug
> of dhcpcd in RH7.2.

This is nice.  One regression noticed is windows 98 SE with the ne2k_isa
card.  It used to obtain an ip address at boot time without this patch -
now it obtains a garbage address 169.x.x.x.  Works great with ne2k_pci.

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

* Re: [Qemu-devel][PATCH] Built-in DHCP server
  2007-02-20 14:22 ` Lonnie Mendez
@ 2007-02-21  8:01   ` Kazu
  0 siblings, 0 replies; 3+ messages in thread
From: Kazu @ 2007-02-21  8:01 UTC (permalink / raw)
  To: qemu-devel


Sent: Tuesday, February 20, 2007 11:22 PM Lonnie Mendez wrote:


> On Tue, 2007-02-20 at 13:09 +0900, Kazu wrote:
>> Hi,
>>
>> After I used TAP device by -net nic -net tap,ifname=mytap and I tried to
use
>> user mode network by -net nic -net user, a Windows XP guest doesn't get
>> IP address from a built-in DHCP server.
>>
>> It is fixed by an attached patch.
>>
>> DHCPRELEASE and DHCPNACK are introduced.
>>
>> DHCPRELEASE code is borrowed from VirtualBox. Windows 2000/XP tries to
call
>> DHCPREQUEST and get old IP address when it boots. I made a code to reply
>> DHCPNACK to the request. Then the Win2k/XP called DHCPDISCOVER and try to
>> get a new IP address.
>>
>> I tested Windows 98SE/2000/XP, Knoppix 3.8, Morphix, Fedora Core 3 and
>> RedHat 7.2 guest.
>> There is not problem except RH7.2. It can get IP address but it is
>> 10.0.2.16. dhcpcd in RH7.2 tries to call DHCPDISCOVER two times. So it
>> consumes two entries in the built-in DHCP server. It seems that it is a
bug
>> of dhcpcd in RH7.2.
>
> This is nice.  One regression noticed is windows 98 SE with the ne2k_isa
> card.  It used to obtain an ip address at boot time without this patch -
> now it obtains a garbage address 169.x.x.x.  Works great with ne2k_pci.
>

Thank you for your information. I tested ne2k_isa. The problem is that DHCP
packet is received only one time, if ne2k_isa is used. It is strange that
once DHCP paket is received, no more packet appear in DHCP server and
Win98SE geust. So Win98SE holds old IP address if without patch. I found
that -net nic,model=ne2k_isa -net user works but -M isapc option stops QEMU
with unhandled Win32 exception. It seems that ISA emulation is broken
somewhere.

Regards,
Kazu

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

end of thread, other threads:[~2007-02-21  8:01 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-20  4:09 [Qemu-devel][PATCH] Built-in DHCP server Kazu
2007-02-20 14:22 ` Lonnie Mendez
2007-02-21  8:01   ` Kazu

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.