DHCP packets – aren’t they always supposed to be broadcasted

dhcpprotocol-theory

So, as I understand it, all DHCP/BOOTP REQUEST packets are supposed to be broadcasted (255.255.255.255), because that's really the only way to communicate back and forth with a host on a LAN that doesn't have an IP address. I have some info from a PCAP file (pasted below) where I had disconnected a machine from the network (hostname debian2) and then reconnected it. The firewall/DHCP server I'm using is pfSense. This is all happening in a Virtualbox host-only network (where that virtual network has DHCP turned off – the only thing doing DHCP is pfSense).

I notice that in both the Offer and the Ack, the destination IP address is the one that pfSense was offering to debian2 (192.168.1.10). How in the world does debian2 receive that packet if it isn't supposed to have configured itself with the offered IP address yet? Why isn't pfSense broadcasting (sending to 255.255.255.255), and how is debian2 receiving it if the destination IP address was one that it wasn't yet configured to use? Is it that pfSense is just using Ethernet and the client's MAC address so the specified destination IP address doesn't really matter?


Frame summaries:

43  19.808108   0.0.0.0 255.255.255.255 DHCP    344 DHCP Discover - Transaction ID 0x1caf7b43
48  20.810107   192.168.1.1 192.168.1.10    DHCP    344 DHCP Offer    - Transaction ID 0x1caf7b43
49  20.810864   0.0.0.0 255.255.255.255 DHCP    344 DHCP Request  - Transaction ID 0x1caf7b43
50  20.812807   192.168.1.1 192.168.1.10    DHCP    344 DHCP ACK      - Transaction ID 0x1caf7b43

Frame details:

Frame 43: 344 bytes on wire (2752 bits), 344 bytes captured (2752 bits)
Linux cooked capture
Internet Protocol Version 4, Src: 0.0.0.0, Dst: 255.255.255.255
User Datagram Protocol, Src Port: 68, Dst Port: 67
Bootstrap Protocol (Discover)
    Message type: Boot Request (1)
    Hardware type: Ethernet (0x01)
    Hardware address length: 6
    Hops: 0
    Transaction ID: 0x1caf7b43
    Seconds elapsed: 0
    Bootp flags: 0x0000 (Unicast)
    Client IP address: 0.0.0.0
    Your (client) IP address: 0.0.0.0
    Next server IP address: 0.0.0.0
    Relay agent IP address: 0.0.0.0
    Client MAC address: PcsCompu_82:09:fa (08:00:27:82:09:fa)
    Client hardware address padding: 00000000000000000000
    Server host name not given
    Boot file name not given
    Magic cookie: DHCP
    Option: (53) DHCP Message Type (Discover)
        Length: 1
        DHCP: Discover (1)
    Option: (50) Requested IP Address
        Length: 4
        Requested IP Address: 192.168.1.8
    Option: (12) Host Name
        Length: 7
        Host Name: debian2
    Option: (55) Parameter Request List
        Length: 13
        Parameter Request List Item: (1) Subnet Mask
        Parameter Request List Item: (28) Broadcast Address
        Parameter Request List Item: (2) Time Offset
        Parameter Request List Item: (3) Router
        Parameter Request List Item: (15) Domain Name
        Parameter Request List Item: (6) Domain Name Server
        Parameter Request List Item: (119) Domain Search
        Parameter Request List Item: (12) Host Name
        Parameter Request List Item: (44) NetBIOS over TCP/IP Name Server
        Parameter Request List Item: (47) NetBIOS over TCP/IP Scope
        Parameter Request List Item: (26) Interface MTU
        Parameter Request List Item: (121) Classless Static Route
        Parameter Request List Item: (42) Network Time Protocol Servers
    Option: (255) End
        Option End: 255
    Padding: 000000000000000000000000000000000000000000000000...


Frame 48: 344 bytes on wire (2752 bits), 344 bytes captured (2752 bits)
Linux cooked capture
Internet Protocol Version 4, Src: 192.168.1.1, Dst: 192.168.1.10
User Datagram Protocol, Src Port: 67, Dst Port: 68
Bootstrap Protocol (Offer)
    Message type: Boot Reply (2)
    Hardware type: Ethernet (0x01)
    Hardware address length: 6
    Hops: 0
    Transaction ID: 0x1caf7b43
    Seconds elapsed: 0
    Bootp flags: 0x0000 (Unicast)
    Client IP address: 0.0.0.0
    Your (client) IP address: 192.168.1.10
    Next server IP address: 0.0.0.0
    Relay agent IP address: 0.0.0.0
    Client MAC address: PcsCompu_82:09:fa (08:00:27:82:09:fa)
    Client hardware address padding: 00000000000000000000
    Server host name not given
    Boot file name not given
    Magic cookie: DHCP
    Option: (53) DHCP Message Type (Offer)
        Length: 1
        DHCP: Offer (2)
    Option: (54) DHCP Server Identifier
        Length: 4
        DHCP Server Identifier: 192.168.1.1
    Option: (51) IP Address Lease Time
        Length: 4
        IP Address Lease Time: (61s) 1 minute, 1 second
    Option: (1) Subnet Mask
        Length: 4
        Subnet Mask: 255.255.255.0
    Option: (3) Router
        Length: 4
        Router: 192.168.1.1
    Option: (15) Domain Name
        Length: 9
        Domain Name: me.net
    Option: (6) Domain Name Server
        Length: 4
        Domain Name Server: 192.168.1.1
    Option: (255) End
        Option End: 255
    Padding: 000000000000000000000000000000


Frame 49: 344 bytes on wire (2752 bits), 344 bytes captured (2752 bits)
Linux cooked capture
Internet Protocol Version 4, Src: 0.0.0.0, Dst: 255.255.255.255
User Datagram Protocol, Src Port: 68, Dst Port: 67
Bootstrap Protocol (Request)
    Message type: Boot Request (1)
    Hardware type: Ethernet (0x01)
    Hardware address length: 6
    Hops: 0
    Transaction ID: 0x1caf7b43
    Seconds elapsed: 0
    Bootp flags: 0x0000 (Unicast)
    Client IP address: 0.0.0.0
    Your (client) IP address: 0.0.0.0
    Next server IP address: 0.0.0.0
    Relay agent IP address: 0.0.0.0
    Client MAC address: PcsCompu_82:09:fa (08:00:27:82:09:fa)
    Client hardware address padding: 00000000000000000000
    Server host name not given
    Boot file name not given
    Magic cookie: DHCP
    Option: (53) DHCP Message Type (Request)
        Length: 1
        DHCP: Request (3)
    Option: (54) DHCP Server Identifier
        Length: 4
        DHCP Server Identifier: 192.168.1.1
    Option: (50) Requested IP Address
        Length: 4
        Requested IP Address: 192.168.1.10
    Option: (12) Host Name
        Length: 7
        Host Name: debian2
    Option: (55) Parameter Request List
        Length: 13
        Parameter Request List Item: (1) Subnet Mask
        Parameter Request List Item: (28) Broadcast Address
        Parameter Request List Item: (2) Time Offset
        Parameter Request List Item: (3) Router
        Parameter Request List Item: (15) Domain Name
        Parameter Request List Item: (6) Domain Name Server
        Parameter Request List Item: (119) Domain Search
        Parameter Request List Item: (12) Host Name
        Parameter Request List Item: (44) NetBIOS over TCP/IP Name Server
        Parameter Request List Item: (47) NetBIOS over TCP/IP Scope
        Parameter Request List Item: (26) Interface MTU
        Parameter Request List Item: (121) Classless Static Route
        Parameter Request List Item: (42) Network Time Protocol Servers
    Option: (255) End
        Option End: 255
    Padding: 0000000000000000000000000000000000000000



Frame 50: 344 bytes on wire (2752 bits), 344 bytes captured (2752 bits)
Linux cooked capture
Internet Protocol Version 4, Src: 192.168.1.1, Dst: 192.168.1.10
User Datagram Protocol, Src Port: 67, Dst Port: 68
Bootstrap Protocol (ACK)
    Message type: Boot Reply (2)
    Hardware type: Ethernet (0x01)
    Hardware address length: 6
    Hops: 0
    Transaction ID: 0x1caf7b43
    Seconds elapsed: 0
    Bootp flags: 0x0000 (Unicast)
    Client IP address: 0.0.0.0
    Your (client) IP address: 192.168.1.10
    Next server IP address: 0.0.0.0
    Relay agent IP address: 0.0.0.0
    Client MAC address: PcsCompu_82:09:fa (08:00:27:82:09:fa)
    Client hardware address padding: 00000000000000000000
    Server host name not given
    Boot file name not given
    Magic cookie: DHCP
    Option: (53) DHCP Message Type (ACK)
        Length: 1
        DHCP: ACK (5)
    Option: (54) DHCP Server Identifier
        Length: 4
        DHCP Server Identifier: 192.168.1.1
    Option: (51) IP Address Lease Time
        Length: 4
        IP Address Lease Time: (61s) 1 minute, 1 second
    Option: (1) Subnet Mask
        Length: 4
        Subnet Mask: 255.255.255.0
    Option: (3) Router
        Length: 4
        Router: 192.168.1.1
    Option: (15) Domain Name
        Length: 9
        Domain Name: me.net
    Option: (6) Domain Name Server
        Length: 4
        Domain Name Server: 192.168.1.1
    Option: (255) End
        Option End: 255
    Padding: 000000000000000000000000000000

Best Answer

DHCP packets - aren't they always supposed to be broadcasted?

No, DHCP offers can be sent as unicast or broadcast. The layer-3 address doesn't really matter if it is unicast or broadcast because the frame is being delivered on the LAN by the layer-2 address.

From RFC 2321, Dynamic Host Configuration Protocol (emphasis mine):

In the case of a client using DHCP for initial configuration (before the client's TCP/IP software has been completely configured), DHCP requires creative use of the client's TCP/IP software and liberal interpretation of RFC 1122. The TCP/IP software SHOULD accept and forward to the IP layer any IP packets delivered to the client's hardware address before the IP address is configured; DHCP servers and BOOTP relay agents may not be able to deliver DHCP messages to clients that cannot accept hardware unicast datagrams before the TCP/IP software is configured.

To work around some clients that cannot accept IP unicast datagrams before the TCP/IP software is configured as discussed in the previous paragraph, DHCP uses the 'flags' field [21]. The leftmost bit is defined as the BROADCAST (B) flag. The semantics of this flag are discussed in section 4.1 of this document. The remaining bits of the flags field are reserved for future use. They MUST be set to zero by clients and ignored by servers and relay agents. Figure 2 gives the format of the 'flags' field.

                              1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |B|             MBZ             |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          B:  BROADCAST flag
          MBZ:  MUST BE ZERO (reserved for future use)
          Figure 2:  Format of the 'flags' field