[klibc] ipconfig:About the length of 'options' field of DHCP packet

maximilian attems max at stro.at
Sun Jul 31 02:07:08 PDT 2011


hello,

On Tue, 19 Jul 2011, KUMAAN wrote:

> 
> I had the problem that 'ipconfig' as DHCP client in Debian-squeeze could not get
> DHCP Offer reply from the built-in DHCP server of the cheap route that I have.
> The name of the router  is 'MegaBitGear TE4571E' which 
> I got at contract of ADSL Internet access service in 2009.
> The router is not too old and can reply to other 
> DHCP clients like ISC-dhclient, WindowsXP and Vista.
> 
> This is why I tried to change the 'ipconfig' code a bit
> paying attention to compatibility with now code, other clients and RFC.
> Concretely, I added the function to 'ipconfig' that append padding to
> the 'options' field of DHCP Discover and Request packet like ISC-dhclient.
> This function is enabled if 'ipconfig' fail to get DHCP Offer reply, 
> retry to send DHCP Discover and the length of the 'options' field is
> shorter than 64 octets.
> 
> I inspected the octet length of 'options' field of DHCP Discover and Request packets 
> which other DHCP clients in default settings send by using Wireshark.
> 'p' means that padding is included.
> 
> Dis. Req. Client
>  35   47  ipconfig(master of git)
>  64p  64p isc-dhclient(4.1.1-P1 in Debian-squeeze)
>  64p  73  WindowsXP 32bit(my x86 PC)
>  64p  76  WindowsVista 64bit(my amd64 PC)

thank you for the analysis.
 
> I referred to RFC2131, RFC1541 and RFC951 for the length of 'options' 
> (called 'vend' in BOOTP) field of DHCP Discover and Request packet.
> Basing on RFC, if the length is ...
> 64 octets:
>  BOOP server which may be able to interpret DHCP too and 
>  DHCP server which can interpret 'options' of variable length will reply.
> 312 octets:
>  DHCP server which can not interpret 'options' of variable length and
>  DHCP server which can interpret 'options' of variable length will reply.
> the others:
>  DHCP server which can interpret 'options' of variable length will reply.
> 
> The above made me think that appending padding 
> might increase the probability of getting DHCP Offer reply.
> Of course appending padding made my cheap router send DHCP Offer reply.
> 
> 
> If you will consider whether this change like the following patch 
> is worth or not, I'm happy.

Hmm first I think we should implement missing options in ipconfig:
domain-search and lease time are the ones that are asked for.
http://bugs.debian.org/627166

If then the padding is still to small, it should be fixed.
In the ISC dhclient I see a BOOTP_MIN_LEN defined to 300.
Without checking with current implementation I'd guess we'd fall
below that?
 
> P.S. Thank you for reading this mail in broken English.

In fact your posting was very clear, sorry for coming back only now,
but had been away for a ten day remote vacations and mailinglist
had a bunch of patches to review and/or merge.

> -- $ git format-patch HEAD^ --
> >From cb6c9c38207ea24df43680282cb1036b78b4c16f Mon Sep 17 00:00:00 2001
> From: KUMAAN <9maaan at gmail.com>
> Date: Tue, 19 Jul 2011 00:12:55 +0900
> Subject: [PATCH] ipconfig:append padding to DHCP options when fail to get reply and retry.
> 
> This patch add the function to ipconfig that append padding to
> the 'options' field of DHCP Discover and Request packet like ISC-dhclient.
> This function is enabled if ipconfig fail to get DHCP Offer reply,
> retry to send DHCP Discover and the length of the 'options' field is
> shorter than 64 octets.

the patch by itself has minor Codingstyle errors, which can be seen
when checked against the scripts/checkpatch.pl in linux source.
(trailing spaces, missing spaces around operators like `=' or ifs)

My main grieve is that we should do it right on the first try
and not only later on.

> ---
>  usr/kinit/ipconfig/bootp_proto.c |    6 ++++++
>  usr/kinit/ipconfig/dhcp_proto.c  |   24 +++++++++++++++++++++++-
>  usr/kinit/ipconfig/main.c        |    6 ++++++
>  usr/kinit/ipconfig/netdev.h      |    1 +
>  4 files changed, 36 insertions(+), 1 deletions(-)
> 
> diff --git a/usr/kinit/ipconfig/bootp_proto.c b/usr/kinit/ipconfig/bootp_proto.c
> index f2cc90c..19c61ef 100644
> --- a/usr/kinit/ipconfig/bootp_proto.c
> +++ b/usr/kinit/ipconfig/bootp_proto.c
> @@ -212,5 +212,11 @@ int bootp_init_if(struct netdev *dev)
>  	dev->bootp.xid = (uint32_t) lrand48();
>  	dev->open_time = time(NULL);
>  
> +	/*
> +	 * 'process_timeout_event(main.c)' will increment 'fail_count'
> +	 * only once independent of a failure.
> +	 */
> +	dev->bootp.fail_count = ~0;
> +
>  	return 0;
>  }
> diff --git a/usr/kinit/ipconfig/dhcp_proto.c b/usr/kinit/ipconfig/dhcp_proto.c
> index afd2eca..91dd695 100644
> --- a/usr/kinit/ipconfig/dhcp_proto.c
> +++ b/usr/kinit/ipconfig/dhcp_proto.c
> @@ -49,7 +49,7 @@ static uint8_t dhcp_end[] = {
>  
>  /* Both iovecs below have to have the same structure, since dhcp_send()
>     pokes at the internals */
> -#define DHCP_IOV_LEN 7
> +#define DHCP_IOV_LEN 8
>  
>  static struct iovec dhcp_discover_iov[DHCP_IOV_LEN] = {
>  	/* [0] = ip + udp header */
> @@ -59,6 +59,7 @@ static struct iovec dhcp_discover_iov[DHCP_IOV_LEN] = {
>  	/* [4] = optional vendor class */
>  	/* [5] = optional hostname */
>  	/* [6] = {dhcp_end, sizeof(dhcp_end)} */
> +	/* [7] = optional padding */
>  };
>  
>  static struct iovec dhcp_request_iov[DHCP_IOV_LEN] = {
> @@ -69,6 +70,7 @@ static struct iovec dhcp_request_iov[DHCP_IOV_LEN] = {
>  	/* [4] = optional vendor class */
>  	/* [5] = optional hostname */
>  	/* [6] = {dhcp_end, sizeof(dhcp_end)} */
> +	/* [7] = optional padding */
>  };
>  
>  /*
> @@ -167,6 +169,7 @@ static int dhcp_send(struct netdev *dev, struct iovec *vec)
>  {
>  	struct bootp_hdr bootp;
>  	char dhcp_hostname[SYS_NMLN+2];
> +	uint8_t options_padding[64];
>  	int i = 4;
>  
>  	memset(&bootp, 0, sizeof(struct bootp_hdr));
> @@ -212,6 +215,25 @@ static int dhcp_send(struct netdev *dev, struct iovec *vec)
>  	vec[i].iov_base = dhcp_end;
>  	vec[i].iov_len  = sizeof(dhcp_end);
>  
> +
> +	if(dev->bootp.fail_count & 1){
> +		/* 
> +		 * Append padding if the length of options field is 
> +		 * shorter than 64 octets. 
> +		 */
> +		int options_padding_len = 64;
> +		int j;
> +		for (j=2; j<=i; j++){
> +			options_padding_len -= vec[j].iov_len;
> +		}
> +		if(options_padding_len > 0){
> +			memset(&options_padding, 0, options_padding_len);
> +			i++;
> +			vec[i].iov_base = options_padding;
> +			vec[i].iov_len  = options_padding_len;
> +		}
> +	}
> +
>  	return packet_send(dev, vec, i + 1);
>  }
>  
> diff --git a/usr/kinit/ipconfig/main.c b/usr/kinit/ipconfig/main.c
> index 8782ae7..b65dd50 100644
> --- a/usr/kinit/ipconfig/main.c
> +++ b/usr/kinit/ipconfig/main.c
> @@ -297,6 +297,12 @@ static void process_timeout_event(struct state *s, time_t now)
>  		s->state = s->restart_state;
>  
>  	/*
> +	 * Except the first arrival, an arrival of this line means 
> +	 * that a failure like a timeout or an error occurred.
> +	 */
> +	s->dev->bootp.fail_count++;
> +
> +	/*
>  	 * Now send a packet depending on our state.
>  	 */
>  	switch (s->state) {
> diff --git a/usr/kinit/ipconfig/netdev.h b/usr/kinit/ipconfig/netdev.h
> index 26d076a..d3b144e 100644
> --- a/usr/kinit/ipconfig/netdev.h
> +++ b/usr/kinit/ipconfig/netdev.h
> @@ -22,6 +22,7 @@ struct netdev {
>  		int fd;
>  		uint32_t xid;
>  		uint32_t gateway; /* BOOTP/DHCP gateway   */
> +		uint8_t fail_count; /* of DHCP Discover or BOOTP/DHCP Request */
>  	} bootp;
>  
>  	struct {		/* RARP information     */
> -- 
> 1.7.2.5

would you mind giving the asked options a try? and if the length
then is too small correct the bootp packet length?

thank you.

-- 
maks



More information about the klibc mailing list