udhcpd offer message,mac broadcast does not comply with rfc2131

bltzmnn bltzmnn at qq.com
Mon Apr 7 02:39:25 UTC 2025


How about this ?


static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast)
{
    const uint8_t *chaddr;
    uint32_t ciaddr;
    int should_broadcast;


    chaddr = dhcp_pkt->chaddr;
    /*
    * force_broadcast for sending DHCPNAK
    * RFC 2131:
    * If 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is
     * set, then the server broadcasts DHCPOFFER and DHCPACK messages to
     * 0xffffffff. ...
    */
    should_broadcast = force_broadcast || (dhcp_pkt->ciaddr == 0 && (dhcp_pkt->flags & htons(BROADCAST_FLAG)));


    if (should_broadcast) {
        log1s("broadcasting packet to client");
        ciaddr = INADDR_BROADCAST;
        chaddr = MAC_BCAST_ADDR;
    } else if (dhcp_pkt->ciaddr != 0) {
        /*
        * If the 'giaddr' field is zero and the 'ciaddr' 
        * field is nonzero, then the server unicasts DHCPOFFER 
        * and DHCPACK messages to the address in 'ciaddr'.
        */
        log1s("unicasting packet to client ciaddr");
        ciaddr = dhcp_pkt->ciaddr;
    } else {
        /*
        * If the broadcast bit is not set and 'giaddr' is zero and
        * 'ciaddr' is zero, then the server unicasts DHCPOFFER and DHCPACK
        * messages to the client's hardware address and 'yiaddr' address.
        */
        log1s("unicasting packet to client yiaddr");
        ciaddr = dhcp_pkt->yiaddr;
    }
...
}










       On Mon, Mar 24, 2025 at 10:10 AM bltzmnn  wrote:
>
> package: busybox
> version: 1.37.0
>
> when I using udhcpd  for a wifi ap,it sends mac broadcast packets in a DHCP OFFER message.This confused me.
>
> In rfc2131:
> ---------------------------------------------------------------------------
> " If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
> set, then the server broadcasts DHCPOFFER and DHCPACK messages to
> 0xffffffff.

Ok...

> If the broadcast bit is not set and ’giaddr’ is zero and
> ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
> messages to the client’s hardware address and ’yiaddr’ address.

And in this case, why would the client receive this packet?
It did not see the DHCPOFFER yet (we are just about to send it)
It does not know YET that what we (the server) filled into
the pkt->yiaddr, and did not configure its IP address to be yiaddr.

Hmmm... looking at our own client code, it has a RAW socket for that,
looking at every IPv4 packet...

How about this?

//if (force_broadcast) { /* broadcast */ }
//else if (dhcp_pkt->ciaddr) { /* unicast to dhcp_pkt->ciaddr */ }
// ^^^ dhcp_pkt->ciaddr comes from client's request packet.
// We expect such clients to have an UDP socket listening on that IP.
//else if (dhcp_pkt->flags & htons(BROADCAST_FLAG)) { /* broadcast */ }
//else { /* unicast to dhcp_pkt->yiaddr */ }
// ^^^ The last case is confusing, but *should* work.
// It's a case where client sent a DISCOVER
// and does not have a kernel UDP socket listening on the IP
// we are offering in yiaddr (it does not know the IP yet)!
// This *should* work because client *should* listen on a raw socket
// instead at this time (IOW: it should examine ALL IPv4 packets
// "by hand", not relying on kernel's UDP stack.)

chaddr = dhcp_pkt->chaddr;

if (dhcp_pkt->ciaddr == 0
|| force_broadcast /* sending DHCPNAK pkt? */
) {
if (dhcp_pkt->flags & htons(BROADCAST_FLAG)
|| force_broadcast /* sending DHCPNAK pkt? */
) {
// RFC 2131:
// If 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is
// set, then the server broadcasts DHCPOFFER and DHCPACK messages to
// 0xffffffff. ...
// In all cases, when 'giaddr' is zero, the server broadcasts any DHCPNAK
// messages to 0xffffffff.
log1s("broadcasting packet to client");
ciaddr = INADDR_BROADCAST;
chaddr = MAC_BCAST_ADDR;
} else {
// If the broadcast bit is not set and 'giaddr' is zero and
// 'ciaddr' is zero, then the server unicasts DHCPOFFER and DHCPACK
// messages to the client's hardware address and 'yiaddr' address.
log1s("unicasting packet to client yiaddr");
ciaddr = dhcp_pkt->yiaddr;
}
} else {
// If the 'giaddr'
// field is zero and the 'ciaddr' field is nonzero, then the server
// unicasts DHCPOFFER and DHCPACK messages to the address in 'ciaddr'.
log1s("unicasting packet to client ciaddr");
ciaddr = dhcp_pkt->ciaddr;
}



> "
> ----------------------------------------------------------------------------
>
> If the code in dhcpd.c should be
>
> -----------------------------------------------------------
> "
> static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast)
> {
> ...
> if (force_broadcast
>  // || (dhcp_pkt->flags & htons(BROADCAST_FLAG))
>  // || dhcp_pkt->ciaddr == 0
>          || ((dhcp_pkt->flags & htons(BROADCAST_FLAG))
>  && dhcp_pkt->ciaddr == 0)
> ...
> }" ?
> ----------------------------------------------------------------------
>
> Not "||" but "&&" ,because the rfc2131 says "If the broadcast bit is not set and ’giaddr’ is zero and
> ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
> messages to the client’s hardware address and ’yiaddr’ address."
>
> Udhcpd works wrong in my ARM board because wifi driver or kernel configs may not  support mac broadcast packets(I don't know why),so I report this bug.
>
> By the way, other dhcp server implementations, isc-dhcp and dnsmasq DHCP OFFER messages all send mac unicast packets.
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> https://lists.busybox.net/mailman/listinfo/busybox
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20250407/800a287e/attachment-0001.htm>


More information about the busybox mailing list