From: renzo@cs.unibo.it (Renzo Davoli)
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [patch] slirp bootp, Request&Discover
Date: Thu, 13 May 2004 17:02:21 +0200 [thread overview]
Message-ID: <20040513150221.GD18157@cs.unibo.it> (raw)
In-Reply-To: <40A28488.5060201@bellard.org>
[-- 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);
prev parent reply other threads:[~2004-05-13 15:11 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
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 message]
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=20040513150221.GD18157@cs.unibo.it \
--to=renzo@cs.unibo.it \
--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 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).