On 2021-11-16 09:56 -07, Joel Knight <knight.j...@gmail.com> wrote:
> Hi. On a firewall recently upgraded to 7.0, I noticed that dhcpleased
> was not getting a reply from my ISP's DHCP server during renewal at
> T1. At T2, dhcpleased would broadcast the REQUEST which would be
> answered. Testing with dhclient showed successful renewals at T1.
>
> Inspecting the REQUEST packets showed that dhclient was setting the
> ciaddr to the existing leased IP address while dhcpleased was not
> setting this field. RFC 2131 4.3.2 (with a nice summary at 4.3.6) is
> pretty strict about when ciaddr and the 'requested ip' option should
> be used. The diff below modifies dhcpleased to set ciaddr and
> 'requested ip' at the appropriate times.

Nice catch. I'd like to solve it a bit differently.
The frontend process should not need to know about protocol state
specifics. The idea is that the engine process tells it to send a packet
and that's it. We are doing the same thing with server_identifier when
we transition to RENEWING, that is, we are setting it to INADDR_ANY so
that the frontend doesn't send it out.

(Unfortunately send_discover() in the frontend needs to know to clear
ciaddr. Maybe a bit of refactoring is in order. Also build_packet's
signature gets a bit out of hand. We should probably just pass in an
interface pointer and be done with it.)

>
> While here, I also noticed that if you configure an interface in
> dhcpleased.conf but do not use "set client id", dhcpleased will not
> send the default client id as is stated in dhcpleased.conf(5).

One problem at a time, I'll extract this out in a bit.

>
> Since gmail will undoubtedly muck up this diff, a clean copy is here:
> www.packetmischief.ca/files/patches/dhcpleased.ciaddr.diff
>
>
> .joel
>

Does this work for you?

diff --git dhcpleased.h dhcpleased.h
index b3b4938ad3c..d209d50a246 100644
--- dhcpleased.h
+++ dhcpleased.h
@@ -296,6 +296,7 @@ struct imsg_req_discover {
 struct imsg_req_request {
        uint32_t                if_index;
        uint32_t                xid;
+       struct in_addr          ciaddr;
        struct in_addr          requested_ip;
        struct in_addr          server_identifier;
        struct in_addr          dhcp_server;
diff --git engine.c engine.c
index 17e65fbe789..3abae44afa4 100644
--- engine.c
+++ engine.c
@@ -1486,6 +1486,10 @@ request_dhcp_request(struct dhcpleased_iface *iface)
        iface->xid = arc4random();
        imsg_req_request.if_index = iface->if_index;
        imsg_req_request.xid = iface->xid;
+       if (iface->state == IF_RENEWING || iface->state == IF_REBINDING)
+               imsg_req_request.ciaddr.s_addr = iface->requested_ip.s_addr;
+       else
+               imsg_req_request.ciaddr.s_addr = 0;
        imsg_req_request.server_identifier.s_addr =
            iface->server_identifier.s_addr;
        imsg_req_request.requested_ip.s_addr = iface->requested_ip.s_addr;
diff --git frontend.c frontend.c
index 5131dce1471..e4b2419c96a 100644
--- frontend.c
+++ frontend.c
@@ -70,6 +70,7 @@ struct iface {
        struct imsg_ifinfo       ifinfo;
        int                      send_discover;
        uint32_t                 xid;
+       struct in_addr           ciaddr;
        struct in_addr           requested_ip;
        struct in_addr           server_identifier;
        struct in_addr           dhcp_server;
@@ -91,7 +92,7 @@ struct iface  *get_iface_by_id(uint32_t);
 void            remove_iface(uint32_t);
 void            set_bpfsock(int, uint32_t);
 ssize_t                 build_packet(uint8_t, char *, uint32_t, struct 
ether_addr *,
-                    struct in_addr *, struct in_addr *);
+                    struct in_addr *, struct in_addr *, struct in_addr *);
 void            send_discover(struct iface *);
 void            send_request(struct iface *);
 void            bpf_send_packet(struct iface *, uint8_t *, ssize_t);
@@ -505,6 +506,7 @@ frontend_dispatch_engine(int fd, short event, void *bula)
                        iface = get_iface_by_id(imsg_req_request.if_index);
                        if (iface != NULL) {
                                iface->xid = imsg_req_request.xid;
+                               iface->ciaddr.s_addr = 
imsg_req_request.ciaddr.s_addr;
                                iface->requested_ip.s_addr =
                                    imsg_req_request.requested_ip.s_addr;
                                iface->server_identifier.s_addr =
@@ -887,7 +889,7 @@ bpf_receive(int fd, short events, void *arg)
 
 ssize_t
 build_packet(uint8_t message_type, char *if_name, uint32_t xid,
-    struct ether_addr *hw_address, struct in_addr *requested_ip,
+    struct ether_addr *hw_address, struct in_addr *ciaddr, struct in_addr 
*requested_ip,
     struct in_addr *server_identifier)
 {
        static uint8_t   dhcp_cookie[] = DHCP_COOKIE;
@@ -926,6 +928,7 @@ build_packet(uint8_t message_type, char *if_name, uint32_t 
xid,
        hdr->hops = 0;
        hdr->xid = xid;
        hdr->secs = 0;
+       hdr->ciaddr.s_addr = ciaddr->s_addr;
        memcpy(hdr->chaddr, hw_address, sizeof(*hw_address));
        p += sizeof(struct dhcp_hdr);
        memcpy(p, dhcp_cookie, sizeof(dhcp_cookie));
@@ -1001,12 +1004,13 @@ send_discover(struct iface *iface)
                return;
        }
        iface->send_discover = 0;
+       iface->ciaddr.s_addr = 0;
 
        if_name = if_indextoname(iface->ifinfo.if_index, ifnamebuf);
        log_debug("DHCPDISCOVER on %s", if_name == NULL ? "?" : if_name);
 
        pkt_len = build_packet(DHCPDISCOVER, if_name, iface->xid,
-           &iface->ifinfo.hw_address, &iface->requested_ip, NULL);
+           &iface->ifinfo.hw_address, &iface->ciaddr, &iface->requested_ip, 
NULL);
        bpf_send_packet(iface, dhcp_packet, pkt_len);
 }
 
@@ -1020,7 +1024,7 @@ send_request(struct iface *iface)
        log_debug("DHCPREQUEST on %s", if_name == NULL ? "?" : if_name);
 
        pkt_len = build_packet(DHCPREQUEST, if_name, iface->xid,
-           &iface->ifinfo.hw_address, &iface->requested_ip,
+           &iface->ifinfo.hw_address, &iface->ciaddr, &iface->requested_ip,
            &iface->server_identifier);
        if (iface->dhcp_server.s_addr != INADDR_ANY) {
                if (udp_send_packet(iface, dhcp_packet, pkt_len) == -1)


-- 
I'm not entirely sure you are real.

Reply via email to