From: Alan T. DeKok Date: Fri, 26 Jan 2024 02:59:57 +0000 (-0500) Subject: allow encoding for foreign options X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e1d048ed96c7fe985bf1569f9454a3464abdb31;p=thirdparty%2Ffreeradius-server.git allow encoding for foreign options --- diff --git a/src/protocols/dhcpv4/base.c b/src/protocols/dhcpv4/base.c index 90fa55ada55..bff36f50b05 100644 --- a/src/protocols/dhcpv4/base.c +++ b/src/protocols/dhcpv4/base.c @@ -733,4 +733,5 @@ fr_dict_protocol_t libfreeradius_dhcpv4_dict_protocol = { .subtype_table = subtype_table, .subtype_table_len = NUM_ELEMENTS(subtype_table), .attr_valid = attr_valid, + .encode = fr_dhcpv4_encode_foreign, }; diff --git a/src/protocols/dhcpv4/dhcpv4.h b/src/protocols/dhcpv4/dhcpv4.h index 9d575609125..965989216e6 100644 --- a/src/protocols/dhcpv4/dhcpv4.h +++ b/src/protocols/dhcpv4/dhcpv4.h @@ -166,6 +166,7 @@ bool fr_dhcpv4_is_encodable(void const *item, void const *uctx); void *fr_dhcpv4_next_encodable(fr_dlist_head_t *list, void *to_eval, void *uctx); ssize_t fr_dhcpv4_encode(uint8_t *buffer, size_t buflen, dhcp_packet_t *original, int code, uint32_t xid, fr_pair_list_t *vps); ssize_t fr_dhcpv4_encode_dbuff(fr_dbuff_t *dbuff, dhcp_packet_t *original, int code, uint32_t xid, fr_pair_list_t *vps); +ssize_t fr_dhcpv4_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list); 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/encode.c b/src/protocols/dhcpv4/encode.c index c8c61847ce3..279841346b0 100644 --- a/src/protocols/dhcpv4/encode.c +++ b/src/protocols/dhcpv4/encode.c @@ -756,6 +756,36 @@ ssize_t fr_dhcpv4_encode_option(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *e return fr_dbuff_set(dbuff, &work_dbuff); } +ssize_t fr_dhcpv4_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list) +{ + ssize_t slen; + fr_pair_t *vp; + fr_dcursor_t cursor; + fr_dbuff_t work_dbuff = FR_DBUFF(dbuff); + + (void) fr_dhcpv4_global_init(); + + fr_assert(dict_dhcpv4 != NULL); + + fr_pair_dcursor_iter_init(&cursor, list, fr_dhcpv4_next_encodable, dict_dhcpv4); + + /* + * Loop over all DHCPv4 options. + * + * Unlike fr_dhcpv4_encode_dbuff(), we don't sort the options. If that causes problems, we will + * deal with it later. + */ + while ((vp = fr_dcursor_current(&cursor))) { + slen = fr_dhcpv4_encode_option(&work_dbuff, &cursor, &(fr_dhcpv4_ctx_t){ .root = fr_dict_root(dict_dhcpv4) }); + if (slen <= 0) return slen - fr_dbuff_used(&work_dbuff); + } + + FR_PROTO_TRACE("Foreign option is %zu byte(s)", fr_dbuff_used(&work_dbuff)); + FR_PROTO_HEX_DUMP(dbuff->p, fr_dbuff_used(&work_dbuff), NULL); + + return fr_dbuff_set(dbuff, &work_dbuff); +} + static ssize_t fr_dhcpv4_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len, UNUSED void *proto_ctx) { return fr_dhcpv4_encode_dbuff(&FR_DBUFF_TMP(data, data_len), NULL, 0, 0, vps);