r299512 breaks dhclient on some networks

Don Lewis truckman at FreeBSD.org
Thu May 19 00:19:25 UTC 2016


On 18 May, Ian FREISLICH wrote:
> Hi
> 
> I cannot for the life of me figure out why the change in r299512 breaks
> DHCP on one network I use but not on another network.
>  
> The only clue I can find is that the request whose response is ignored
> has the following client ID:
> 1:6:0:22:5f:70:a1:df
> 
> The request whose response is use has this client ID:
> 1:0:22:5f:70:a1:df
> 
> Here's a dhcpdump of the request/offer that gets ignored.
> 
> ---------------------------------------------------------------------------
> 
>   TIME: 2016-05-18 18:46:39.134
>     IP: 0.0.0.0 (00:22:5f:70:a1:df) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
>     OP: 1 (BOOTPREQUEST)
>  HTYPE: 1 (Ethernet)
>   HLEN: 6
>   HOPS: 0
>    XID: 92a34fc3
>   SECS: 0
>  FLAGS: 0
> CIADDR: 0.0.0.0
> YIADDR: 0.0.0.0
> SIADDR: 0.0.0.0
> GIADDR: 0.0.0.0
> CHADDR: 00:22:5f:70:a1:df:00:00:00:00:00:00:00:00:00:00
>  SNAME: .
>  FNAME: .
> OPTION:  53 (  1) DHCP message type         1 (DHCPDISCOVER)
> OPTION:  61 (  8) Client-identifier         01:06:00:22:5f:70:a1:df
> OPTION:  12 (  3) Host name                 zen
> OPTION:  55 (  9) Parameter Request List      1 (Subnet mask)
>                                              28 (Broadcast address)
>                                               2 (Time offset)
>                                             121 (Classless Static Route)
>                                               3 (Routers)
>                                              15 (Domainname)
>                                               6 (DNS server)
>                                              12 (Host name)
>                                             119 (Domain Search)
>                                            
> ---------------------------------------------------------------------------
> 
>   TIME: 2016-05-18 18:46:39.134
>     IP: 10.0.0.1 (4c:5e:0c:62:4f:82) > 10.0.0.80 (00:22:5f:70:a1:df)
>     OP: 2 (BOOTPREPLY)
>  HTYPE: 1 (Ethernet)
>   HLEN: 6
>   HOPS: 0
>    XID: 92a34fc3
>   SECS: 0
>  FLAGS: 0
> CIADDR: 0.0.0.0
> YIADDR: 10.0.0.80
> SIADDR: 10.0.0.1
> GIADDR: 0.0.0.0
> CHADDR: 00:22:5f:70:a1:df:00:00:00:00:00:00:00:00:00:00
>  SNAME: .
>  FNAME: .
> OPTION:  53 (  1) DHCP message type         2 (DHCPOFFER)
> OPTION:  54 (  4) Server identifier         10.0.0.1
> OPTION:  51 (  4) IP address leasetime      259200 (3d)
> OPTION:   1 (  4) Subnet mask               255.255.255.0
> OPTION:   3 (  4) Routers                   10.0.0.1
> OPTION:   6 (  4) DNS server                10.0.0.1
> ---------------------------------------------------------------------------
> 
> 
> And here's the request/offer that works (with the r299512 backed out)
> 
> ---------------------------------------------------------------------------
> 
>   TIME: 2016-05-18 18:35:33.817
>     IP: 10.0.0.220 (00:22:5f:70:a1:df) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
>     OP: 1 (BOOTPREQUEST)
>  HTYPE: 1 (Ethernet)
>   HLEN: 6
>   HOPS: 0
>    XID: 866cfd85
>   SECS: 4
>  FLAGS: 0
> CIADDR: 0.0.0.0
> YIADDR: 0.0.0.0
> SIADDR: 0.0.0.0
> GIADDR: 0.0.0.0
> CHADDR: 00:22:5f:70:a1:df:00:00:00:00:00:00:00:00:00:00
>  SNAME: .
>  FNAME: .
> OPTION:  53 (  1) DHCP message type         3 (DHCPREQUEST)
> OPTION:  50 (  4) Request IP address        10.0.0.220
> OPTION:  61 (  7) Client-identifier         01:00:22:5f:70:a1:df
> OPTION:  12 (  3) Host name                 zen
> OPTION:  55 (  9) Parameter Request List      1 (Subnet mask)
>                                              28 (Broadcast address)
>                                               2 (Time offset)
>                                             121 (Classless Static Route)
>                                               3 (Routers)
>                                              15 (Domainname)
>                                               6 (DNS server)
>                                              12 (Host name)
>                                             119 (Domain Search)
>                                            
> ---------------------------------------------------------------------------
> 
>   TIME: 2016-05-18 18:35:33.817
>     IP: 10.0.0.1 (4c:5e:0c:62:4f:82) > 10.0.0.220 (00:22:5f:70:a1:df)
>     OP: 2 (BOOTPREPLY)
>  HTYPE: 1 (Ethernet)
>   HLEN: 6
>   HOPS: 0
>    XID: 866cfd85
>   SECS: 0
>  FLAGS: 0
> CIADDR: 0.0.0.0
> YIADDR: 10.0.0.220
> SIADDR: 10.0.0.1
> GIADDR: 0.0.0.0
> CHADDR: 00:22:5f:70:a1:df:00:00:00:00:00:00:00:00:00:00
>  SNAME: .
>  FNAME: .
> OPTION:  53 (  1) DHCP message type         5 (DHCPACK)
> OPTION:  54 (  4) Server identifier         10.0.0.1
> OPTION:  51 (  4) IP address leasetime      259200 (3d)
> OPTION:   1 (  4) Subnet mask               255.255.255.0
> OPTION:   3 (  4) Routers                   10.0.0.1
> OPTION:   6 (  4) DNS server                10.0.0.1
> ---------------------------------------------------------------------------

It looks to me like r299512 is changing the format of the client
identifier by inserting the struct hardware hlen field into it.  That's
not valid if htype is non-zero the way I interpret RFC 2132.  On the
other hand, I would think that the server would interpret the client ID
as an opaque cookie, so I wouldn't think it would make a difference
(other than thinking this is a new client) unless your server is
configured to look for specific client IDs.

I think that r299512 is mostly incorrect and should be reverted.  The
problem reported by CID 1008682 is an overrun of hw_address.haddr.
struct hardware looks like this:

struct hardware {
        u_int8_t htype;
        u_int8_t hlen;
        u_int8_t haddr[16];
};

I think the correct fix is just this:

                size_t hwlen = MIN(ip->hw_address.hlen,
                    sizeof(ip->hw_address.haddr));

The old code was wrong because sizeof(client_ident)-1 is the
same as sizeof(struct hardware)-1, when it should be -2 to exclude both
htype and hlen from the calculation.

The fix for CID 1305550 looks correct.


The following patch has been compile tested:

Index: dhclient.c
===================================================================
--- dhclient.c	(revision 300099)
+++ dhclient.c	(working copy)
@@ -1572,18 +1572,16 @@
 	}
 
 	/* set unique client identifier */
-	struct hardware client_ident;
+	char client_ident[sizeof(struct hardware)];
 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
 		size_t hwlen = MIN(ip->hw_address.hlen,
-		    sizeof(client_ident.haddr));
-		client_ident.htype = ip->hw_address.htype;
-		client_ident.hlen = hwlen;
-		memcpy(client_ident.haddr, ip->hw_address.haddr, hwlen);
+		    sizeof(ip->hw_address.haddr));
+		client_ident[0] = ip->hw_address.htype;
+		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
-		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = (void *)&client_ident;
-		hwlen += offsetof(struct hardware, haddr);
-		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen;
-		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen;
+		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
+		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
+		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
 	}
 



More information about the freebsd-current mailing list