On 2021-11-23 21:30 -07, Joel Knight <knight.j...@gmail.com> wrote: > On Fri, Nov 19, 2021 at 1:01 PM Joel Knight <knight.j...@gmail.com> wrote: >> >> One thing that got missed in the refactor was that the requested-ip >> option should not be set in a RENEWING or BINDING state (or in other >> words, when ciaddr is set). This chunk on top of your diff also works >> as expected (successful unicast renewal at T1).
Thanks, I had indeed missed this. I went through the RFC and found that we MUST NOT send the server identifier in rebooting state. While here I also made it explicit that we are not sending server identifier in rebinding state. This was already the case since we only transition from renewing to rebinding, but this is clearer. > > Hi Florian, > > Does the chunk below make sense? No, this needs to be fixed in the engine, like this: | $ git diff --relative | diff --git engine.c engine.c | index 3abae44afa4..ee999b27bcd 100644 | --- engine.c | +++ engine.c | @@ -1357,6 +1357,7 @@ state_transition(struct dhcpleased_iface *iface, enum if_state new_state) | else { | /* make sure we send broadcast */ | iface->dhcp_server.s_addr = INADDR_ANY; | + iface->server_identifier.s_addr = INADDR_ANY; | iface->timo.tv_sec = START_EXP_BACKOFF; | } | request_dhcp_request(iface); | @@ -1393,6 +1394,7 @@ state_transition(struct dhcpleased_iface *iface, enum if_state new_state) | case IF_REBINDING: | if (old_state == IF_RENEWING) { | iface->dhcp_server.s_addr = INADDR_ANY; | + iface->server_identifier.s_addr = INADDR_ANY; | iface->timo.tv_sec = (iface->lease_time - | iface->rebinding_time) / 2; /* RFC 2131 4.4.5 */ | } else | @@ -1492,7 +1494,11 @@ request_dhcp_request(struct dhcpleased_iface *iface) | 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; | + if (iface->state == IF_RENEWING || iface->state == IF_REBINDING) | + imsg_req_request.requested_ip.s_addr = 0; | + else | + imsg_req_request.requested_ip.s_addr = | + iface->requested_ip.s_addr; | imsg_req_request.dhcp_server.s_addr = iface->dhcp_server.s_addr; | engine_imsg_compose_frontend(IMSG_SEND_REQUEST, 0, &imsg_req_request, | sizeof(imsg_req_request)); This is the complete diff. 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..ee999b27bcd 100644 --- engine.c +++ engine.c @@ -1357,6 +1357,7 @@ state_transition(struct dhcpleased_iface *iface, enum if_state new_state) else { /* make sure we send broadcast */ iface->dhcp_server.s_addr = INADDR_ANY; + iface->server_identifier.s_addr = INADDR_ANY; iface->timo.tv_sec = START_EXP_BACKOFF; } request_dhcp_request(iface); @@ -1393,6 +1394,7 @@ state_transition(struct dhcpleased_iface *iface, enum if_state new_state) case IF_REBINDING: if (old_state == IF_RENEWING) { iface->dhcp_server.s_addr = INADDR_ANY; + iface->server_identifier.s_addr = INADDR_ANY; iface->timo.tv_sec = (iface->lease_time - iface->rebinding_time) / 2; /* RFC 2131 4.4.5 */ } else @@ -1486,9 +1488,17 @@ 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; + if (iface->state == IF_RENEWING || iface->state == IF_REBINDING) + imsg_req_request.requested_ip.s_addr = 0; + else + imsg_req_request.requested_ip.s_addr = + iface->requested_ip.s_addr; imsg_req_request.dhcp_server.s_addr = iface->dhcp_server.s_addr; engine_imsg_compose_frontend(IMSG_SEND_REQUEST, 0, &imsg_req_request, sizeof(imsg_req_request)); diff --git frontend.c frontend.c index bd1e37fe952..3816a31689c 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,8 @@ 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,8 +890,8 @@ 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 in_addr *server_identifier) + 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; static uint8_t dhcp_message_type[] = {DHO_DHCP_MESSAGE_TYPE, 1, @@ -926,6 +929,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)); @@ -1005,12 +1009,14 @@ 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); } @@ -1024,7 +1030,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.