qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [patch] slirp bootp, Request&Discover
@ 2004-05-12 15:30 Renzo Davoli
  2004-05-12 20:09 ` Fabrice Bellard
  0 siblings, 1 reply; 3+ messages in thread
From: Renzo Davoli @ 2004-05-12 15:30 UTC (permalink / raw)
  To: qemu-devel

I have done some tests with Win98.

Sometimes it starts asking for an address with a DHCPdiscover 
sometimes with a DHCPrequest.
In the latter case using the current cvs of bootp.c there is no answer
as there is no MAC address registered yet.

Maybe it is a workaround (although a working workaround ;-) but I
propose to manage a DHCPrequest with no registered MAC address as it
were a DHCPdiscover.

The patch is here enclosed.

ciao
	renzo

-----------
--- bootp.cvs.c     2004-05-04 14:20:25.000000000 +0200
+++ bootp.c     2004-05-12 17:19:50.000000000 +0200
@@ -149,20 +149,18 @@
     m->m_data += sizeof(struct udpiphdr);
     memset(rbp, 0, sizeof(struct bootp_t));
 
-    if (dhcp_msg_type == DHCPDISCOVER) {
+    bc=NULL;
+    if (dhcp_msg_type == DHCPREQUEST)
+           bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
+    if (!bc) {
         bc = get_new_addr(&daddr.sin_addr);
         if (!bc) {
             dprintf("no address left\n");
             return;
         }
         memcpy(bc->macaddr, client_ethaddr, 6);
-    } else {
-        bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
-        if (!bc) {
-            dprintf("no address assigned\n");
-            return;
-        }
     }
+
     dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
 
     saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) |
CTL_ALIAS);

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

* Re: [Qemu-devel] [patch] slirp bootp, Request&Discover
  2004-05-12 15:30 [Qemu-devel] [patch] slirp bootp, Request&Discover Renzo Davoli
@ 2004-05-12 20:09 ` Fabrice Bellard
  2004-05-13 15:02   ` Renzo Davoli
  0 siblings, 1 reply; 3+ messages in thread
From: Fabrice Bellard @ 2004-05-12 20:09 UTC (permalink / raw)
  To: qemu-devel

Strange. If a real DHCP server accepts that, then I agree to merge it. 
Otherwise, it may be bug in the NE2000 emulation.

Fabrice.

Renzo Davoli wrote:
> I have done some tests with Win98.
> 
> Sometimes it starts asking for an address with a DHCPdiscover 
> sometimes with a DHCPrequest.
> In the latter case using the current cvs of bootp.c there is no answer
> as there is no MAC address registered yet.
> 
> Maybe it is a workaround (although a working workaround ;-) but I
> propose to manage a DHCPrequest with no registered MAC address as it
> were a DHCPdiscover.
> 
> The patch is here enclosed.
> 
> ciao
> 	renzo
> 
> -----------
> --- bootp.cvs.c     2004-05-04 14:20:25.000000000 +0200
> +++ bootp.c     2004-05-12 17:19:50.000000000 +0200
> @@ -149,20 +149,18 @@
>      m->m_data += sizeof(struct udpiphdr);
>      memset(rbp, 0, sizeof(struct bootp_t));
>  
> -    if (dhcp_msg_type == DHCPDISCOVER) {
> +    bc=NULL;
> +    if (dhcp_msg_type == DHCPREQUEST)
> +           bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
> +    if (!bc) {
>          bc = get_new_addr(&daddr.sin_addr);
>          if (!bc) {
>              dprintf("no address left\n");
>              return;
>          }
>          memcpy(bc->macaddr, client_ethaddr, 6);
> -    } else {
> -        bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
> -        if (!bc) {
> -            dprintf("no address assigned\n");
> -            return;
> -        }
>      }
> +
>      dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
>  
>      saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) |
> CTL_ALIAS);
> 
> 
> 
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://mail.nongnu.org/mailman/listinfo/qemu-devel
> 

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

* Re: [Qemu-devel] [patch] slirp bootp, Request&Discover
  2004-05-12 20:09 ` Fabrice Bellard
@ 2004-05-13 15:02   ` Renzo Davoli
  0 siblings, 0 replies; 3+ messages in thread
From: Renzo Davoli @ 2004-05-13 15:02 UTC (permalink / raw)
  To: qemu-devel

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

On Wed, May 12, 2004 at 10:09:44PM +0200, Fabrice Bellard wrote:
> Strange. If a real DHCP server accepts that, then I agree to merge it. 
> Otherwise, it may be bug in the NE2000 emulation.

AFAIK it is not strange.

DHCP request is sent also for renewing a lease.
you use a very long lease time (1 day) but it seems that win 98 despite
of a boot remembers that it already had a lease and asks just for a renewal.

I have written a new patch that not only solves this problem but it
gives also a better approximation of the DHCP protocol by managing 
a simplified version of the lease protocol.

It is useful for using qemu with user-net for a period of time longer than the 
lease expire time (or to connect several interfaces-machines to the dhcp
server).

This patch:
- tries to reaasign the previous address to each MAC address.
- if there are no more available addresses re-assigns IP with expired
  leases.
- If somebody tries to DISCOVER multiple times sends back the same
  address (Win 98 ask several times when the address has changed)
- When REQUEST asks for an already assigned address returns DHCPNAK
  (unfortunately Win 98 does not manage this correctly).
  When 98 has a valid lease from a previous session it asks twice for
  the previous address and regardless of the NAK coming from the server it tests
  with a ping whether the address is available or not and *keeps it*!
  IMHO this is plain against the RFC 2131.

Fabrice,
I am including this into slirpvde, maybe my previous fix is enough for
dhcp inside qemu (as it has a single guest machine) but if you like we
can keep the source code aligned.

ciao
	renzo


[-- Attachment #2: bootp.diff --]
[-- Type: text/plain, Size: 4849 bytes --]

--- oldbootp.c	2004-05-03 14:11:44.000000000 +0200
+++ bootp.c	2004-05-13 16:57:08.000000000 +0200
@@ -29,10 +29,12 @@
 
 #define START_ADDR 15
 
-#define LEASE_TIME (24 * 3600)
+#define LEASE_TIME (120)
 
 typedef struct {
     uint8_t allocated;
+    uint8_t macaddr[6];
+    int time;
 } BOOTPClient;
 
 BOOTPClient bootp_clients[NB_ADDR];
@@ -50,26 +52,69 @@
 {
     BOOTPClient *bc;
     int i;
+    int now=time(NULL);
 
     for(i = 0; i < NB_ADDR; i++) {
         if (!bootp_clients[i].allocated)
             goto found;
     }
+    for(i = 0; i < NB_ADDR; i++) {
+        if (now-bootp_clients[i].time > 3*LEASE_TIME)
+            goto found;
+    }
     return NULL;
  found:
     bc = &bootp_clients[i];
-    bc->allocated = 1;
     paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
     return bc;
 }
 
+static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
+{
+    BOOTPClient *bc;
+    int i;
+
+    for(i = 0; i < NB_ADDR; i++) {
+        if (!memcmp(macaddr, bootp_clients[i].macaddr, 6))
+            goto found;
+    }
+    return NULL;
+ found:
+    bc = &bootp_clients[i];
+    paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+    return bc;
+}
+
+static BOOTPClient *find_reqaddr(struct in_addr *paddr, struct in_addr *reqaddr, const uint8_t *macaddr)
+{
+    BOOTPClient *bc=NULL;
+    int i;
+    /*check the net prefix*/
+    if ((ntohl(reqaddr->s_addr) & 0xffffff00) ==
+		    (ntohl(special_addr.s_addr) & 0xffffff00)) {
+	    i=(ntohl(reqaddr->s_addr) & 0xff) - START_ADDR;
+	    if (i>=0 && i< NB_ADDR) {
+		    bc = &bootp_clients[i];
+		    if (bc->allocated &&
+				    (memcmp(macaddr, bootp_clients[i].macaddr, 6)==0)) {
+			    paddr->s_addr = reqaddr->s_addr;
+			    return bc;
+		    }
+		    else
+			    bc=NULL;
+	    }
+    }
+    return bc;
+}
+
 static void dhcp_decode(const uint8_t *buf, int size,
-                        int *pmsg_type)
+                        int *pmsg_type, struct sockaddr_in *preqaddr)
 {
     const uint8_t *p, *p_end;
     int len, tag;
 
     *pmsg_type = 0;    
+    preqaddr->sin_addr.s_addr=htonl(0L);
 
     p = buf;
     p_end = buf + size;
@@ -96,6 +141,10 @@
                 if (len >= 1)
                     *pmsg_type = p[0];
                 break;
+            case RFC2132_REQ_ADDR:
+		if (len == 4) {
+			memcpy(&(preqaddr->sin_addr),p,4);
+		}
             default:
                 break;
             }
@@ -109,14 +158,14 @@
     BOOTPClient *bc;
     struct mbuf *m;
     struct bootp_t *rbp;
-    struct sockaddr_in saddr, daddr;
+    struct sockaddr_in saddr, daddr, reqaddr;
     struct in_addr dns_addr;
     int dhcp_msg_type, val;
-    uint8_t *q;
+    uint8_t *q,replytype;
 
     /* extract exact DHCP msg type */
-    dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
-    dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
+    dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type,&reqaddr);
+    dprintf("bootp packet op=%d msgtype=%d reqaddr=%x\n", bp->bp_op, dhcp_msg_type,ntohl(reqaddr.sin_addr.s_addr));
     
     if (dhcp_msg_type != DHCPDISCOVER && 
         dhcp_msg_type != DHCPREQUEST)
@@ -131,11 +180,20 @@
     m->m_data += sizeof(struct udpiphdr);
     memset(rbp, 0, sizeof(struct bootp_t));
 
+    bc=NULL;
+    daddr.sin_addr.s_addr=htonl(0L);
+    if (dhcp_msg_type == DHCPREQUEST) {
+	    if (reqaddr.sin_addr.s_addr != htonl(0L))
+		    bc = find_reqaddr(&daddr.sin_addr, &reqaddr.sin_addr, bp->bp_hwaddr);
+	    else 
+		    bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
+    }
+    else if (dhcp_msg_type == DHCPDISCOVER) {
+	    bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
+	    if (!bc)
     bc = get_new_addr(&daddr.sin_addr);
-    if (!bc) {
-        dprintf("no address left\n");
-        return;
     }
+
     dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
 
     saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
@@ -155,18 +213,21 @@
     memcpy(q, rfc1533_cookie, 4);
     q += 4;
 
-    if (dhcp_msg_type == DHCPDISCOVER) {
-        *q++ = RFC2132_MSG_TYPE;
-        *q++ = 1;
-        *q++ = DHCPOFFER;
-    } else if (dhcp_msg_type == DHCPREQUEST) {
+    if (bc != NULL) {
+        memcpy(bc->macaddr, client_ethaddr, 6);
+    	bc->allocated = 1;
+	bc->time = time(NULL);
+    	replytype=(dhcp_msg_type == DHCPDISCOVER)?DHCPOFFER:DHCPACK;
+    }
+    else
+	replytype=DHCPNACK;
+
         *q++ = RFC2132_MSG_TYPE;
         *q++ = 1;
-        *q++ = DHCPACK;
-    }
+    *q++ = replytype;
         
-    if (dhcp_msg_type == DHCPDISCOVER ||
-        dhcp_msg_type == DHCPREQUEST) {
+    if ((dhcp_msg_type == DHCPDISCOVER ||
+        dhcp_msg_type == DHCPREQUEST) && replytype!=DHCPNACK) {
         *q++ = RFC2132_SRV_ID;
         *q++ = 4;
         memcpy(q, &saddr.sin_addr, 4);

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

end of thread, other threads:[~2004-05-13 15:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-12 15:30 [Qemu-devel] [patch] slirp bootp, Request&Discover Renzo Davoli
2004-05-12 20:09 ` Fabrice Bellard
2004-05-13 15:02   ` Renzo Davoli

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).