diff --git a/src/modules/proto_dhcpv4/proto_dhcpv4.c b/src/modules/proto_dhcpv4/proto_dhcpv4.c index cd2f346da507..0f13b4661d65 100644 --- a/src/modules/proto_dhcpv4/proto_dhcpv4.c +++ b/src/modules/proto_dhcpv4/proto_dhcpv4.c @@ -397,7 +397,7 @@ static ssize_t mod_encode(void const *instance, REQUEST *request, uint8_t *buffe if (data_len > 0) return data_len; } - data_len = fr_dhcpv4_encode(buffer, buffer_len, + data_len = fr_dhcpv4_encode(buffer, buffer_len, original, request->reply->code, ntohl(original->xid), request->reply->vps); if (data_len < 0) { RPEDEBUG("Failed encoding DHCPV4 reply"); diff --git a/src/protocols/dhcpv4/base.c b/src/protocols/dhcpv4/base.c index 463e4eba4a61..2165461e5e97 100644 --- a/src/protocols/dhcpv4/base.c +++ b/src/protocols/dhcpv4/base.c @@ -268,7 +268,7 @@ bool fr_dhcpv4_ok(uint8_t const *data, ssize_t data_len, uint8_t *message_type, return true; } -ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, int code, uint32_t xid, VALUE_PAIR *vps) +ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, int code, dhcp_packet_t *original, uint32_t xid, VALUE_PAIR *vps) { uint8_t *p; fr_cursor_t cursor; @@ -312,17 +312,35 @@ ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, int code, uint32_t xid, /* DHCP-Hardware-Type */ vp = fr_pair_find_by_da(vps, attr_dhcp_hardware_type, TAG_ANY); - if (vp) *p = vp->vp_uint8; + if (vp) { + *p = vp->vp_uint8; + + } else if (original) { + *p = original->htype; + + } /* else leave it unset */ p += 1; /* DHCP-Hardware-Address-len */ vp = fr_pair_find_by_da(vps, attr_dhcp_hardware_address_length, TAG_ANY); - if (vp) *p = vp->vp_uint8; + if (vp) { + *p = vp->vp_uint8; + + } else if (original) { + *p = original->hlen; + + } /* else leave it unset */ p += 1; /* DHCP-Hop-Count */ vp = fr_pair_find_by_da(vps, attr_dhcp_hop_count, TAG_ANY); - if (vp) *p = vp->vp_uint8; + if (vp) { + *p = vp->vp_uint8; + + } else if (original) { + *p = original->hops; + + } /* else leave it unset */ p++; /* DHCP-Transaction-Id */ @@ -377,10 +395,15 @@ ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, int code, uint32_t xid, vp = fr_pair_find_by_da(vps, attr_dhcp_gateway_ip_address, TAG_ANY); if (vp) { lvalue = vp->vp_ipv4addr; + memcpy(p, &lvalue, 4); + + } else if (original) { /* copy whatever value was in the original */ + memcpy(p, original->giaddr, sizeof(original->giaddr)); + } else { lvalue = htonl(INADDR_ANY); + memcpy(p, &lvalue, 4); } - memcpy(p, &lvalue, 4); p += 4; /* DHCP-Client-Hardware-Address */ @@ -394,6 +417,10 @@ ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, int code, uint32_t xid, memcpy(p, vp->vp_ether, sizeof(vp->vp_ether)); } /* else ignore it */ + + } else if (original) { /* copy whatever value was in the original */ + memcpy(p, original->chaddr, sizeof(original->chaddr)); + } p += DHCP_CHADDR_LEN; diff --git a/src/protocols/dhcpv4/dhcpv4.h b/src/protocols/dhcpv4/dhcpv4.h index 8f87c93ebe86..77413096973f 100644 --- a/src/protocols/dhcpv4/dhcpv4.h +++ b/src/protocols/dhcpv4/dhcpv4.h @@ -141,7 +141,7 @@ int8_t fr_dhcpv4_attr_cmp(void const *a, void const *b); bool fr_dhcpv4_ok(uint8_t const *data, ssize_t data_len, uint8_t *message_type, uint32_t *xid); RADIUS_PACKET *fr_dhcpv4_packet_alloc(uint8_t const *data, ssize_t data_len); -ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, int code, uint32_t xid, VALUE_PAIR *vps); +ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, int code, dhcp_packet_t *original, uint32_t xid, VALUE_PAIR *vps); int fr_dhcpv4_global_init(void); void fr_dhcpv4_global_free(void); void fr_dhcpv4_print_hex(FILE *fp, uint8_t const *packet, size_t packet_len); diff --git a/src/protocols/dhcpv4/packet.c b/src/protocols/dhcpv4/packet.c index 73ebd8bdbd5c..06ddf1c6515c 100644 --- a/src/protocols/dhcpv4/packet.c +++ b/src/protocols/dhcpv4/packet.c @@ -348,7 +348,7 @@ int fr_dhcpv4_packet_encode(RADIUS_PACKET *packet) packet->id = fr_rand(); } - len = fr_dhcpv4_encode(packet->data, packet->data_len, packet->code, packet->id, packet->vps); + len = fr_dhcpv4_encode(packet->data, packet->data_len, packet->code, NULL, packet->id, packet->vps); if (len < 0) return -1; packet->data_len = len;