]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add fr_dhcpv4_attr_sizes[] and fr_dhcpv4_option_len()
authorAlan T. DeKok <aland@freeradius.org>
Wed, 16 Mar 2022 13:37:01 +0000 (09:37 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 16 Mar 2022 13:37:01 +0000 (09:37 -0400)
src/protocols/dhcpv4/base.c
src/protocols/dhcpv4/dhcpv4.h

index 00a0a9b20969b5067fc60cbd87257a52f5887fcc..724b4a13b1e156444331dc758e37e470ded51761 100644 (file)
@@ -97,6 +97,31 @@ fr_dict_attr_autoload_t dhcpv4_dict_attr[] = {
        { NULL }
 };
 
+size_t const fr_dhcpv4_attr_sizes[FR_TYPE_MAX + 1][2] = {
+       [FR_TYPE_NULL]          = {~0, 0},
+
+       [FR_TYPE_STRING]                = {0, ~0},
+       [FR_TYPE_OCTETS]                = {0, ~0},
+
+       [FR_TYPE_IPV4_ADDR]             = {4, 4},
+       [FR_TYPE_IPV4_PREFIX]           = {1, 5},       //!< Zero length prefix still requires one byte for prefix len.
+       [FR_TYPE_IPV6_ADDR]             = {16, 16},
+       [FR_TYPE_IPV6_PREFIX]           = {1, 17},      //!< Zero length prefix still requires one byte for prefix len.
+       [FR_TYPE_IFID]                  = {8, 8},
+       [FR_TYPE_ETHERNET]              = {6, 6},
+
+       [FR_TYPE_BOOL]                  = {1, 1},
+       [FR_TYPE_UINT8]                 = {1, 1},
+       [FR_TYPE_UINT16]                = {2, 2},
+       [FR_TYPE_UINT32]                = {4, 4},
+       [FR_TYPE_UINT64]                = {8, 8},
+
+       [FR_TYPE_TLV]                   = {2, ~0},
+       [FR_TYPE_STRUCT]                = {1, ~0},
+
+       [FR_TYPE_MAX]                   = {~0, 0}       //!< Ensure array covers all types.
+};
+
 /*
  *     INADDR_ANY : 68 -> INADDR_BROADCAST : 67        DISCOVER
  *     INADDR_BROADCAST : 68 <- SERVER_IP : 67         OFFER
@@ -201,6 +226,48 @@ int8_t fr_dhcpv4_attr_cmp(void const *a, void const *b)
        return fr_pair_cmp_by_parent_num(my_a, my_b);
 }
 
+/** Return the on-the-wire length of an attribute value
+ *
+ * @param[in] vp to return the length of.
+ * @return the length of the attribute.
+ */
+size_t fr_dhcpv4_option_len(fr_pair_t const *vp)
+{
+       switch (vp->vp_type) {
+       case FR_TYPE_VARIABLE_SIZE:
+#ifndef NDEBUG
+               if (!vp->da->flags.extra &&
+                   (vp->da->flags.subtype == FLAG_ENCODE_DNS_LABEL)) {
+                       fr_assert_fail("DNS labels MUST be encoded/decoded with their own function, and not with generic 'string' functions");
+                       return 0;
+               }
+#endif
+
+               if (vp->da->flags.length) return vp->da->flags.length;  /* Variable type with fixed length */
+
+               /*
+                *      Arrays get maxed at 2^8 - 1
+                */
+               if (vp->da->flags.array && ((vp->vp_type == FR_TYPE_STRING) || (vp->vp_type == FR_TYPE_OCTETS))) {
+                       if (vp->vp_length > 255) return 255;
+               }
+
+               return vp->vp_length;
+
+       case FR_TYPE_DATE:
+       case FR_TYPE_TIME_DELTA:
+               if (vp->data.enumv->flags.length) return vp->data.enumv->flags.length;
+               return sizeof(uint32_t);
+
+       case FR_TYPE_STRUCTURAL:
+               fr_assert_fail(NULL);
+               return 0;
+
+       default:
+               return fr_dhcpv4_attr_sizes[vp->vp_type][0];
+       }
+}
+
 /** Check received DHCP request is valid and build fr_radius_packet_t structure if it is
  *
  * @param data pointer to received packet.
index 7bf7cdd5d699fcf099df32213e5a7f5ba62b40a1..b2ed1b159c58a9a23c39c71d455bb9a41bf7cfba 100644 (file)
@@ -34,6 +34,8 @@ extern "C" {
 #include <freeradius-devel/util/packet.h>
 #include <freeradius-devel/protocol/dhcpv4/rfc2131.h>
 
+extern size_t const fr_dhcpv4_attr_sizes[FR_TYPE_MAX + 1][2];
+
 #define DHCP_CHADDR_LEN        (16)
 #define DHCP_SNAME_LEN (64)
 #define DHCP_FILE_LEN  (128)
@@ -151,6 +153,7 @@ typedef struct {
  */
 int8_t         fr_dhcpv4_attr_cmp(void const *a, void const *b);
 
+size_t         fr_dhcpv4_option_len(fr_pair_t const *vp);
 bool           fr_dhcpv4_ok(uint8_t const *data, ssize_t data_len, uint8_t *message_type, uint32_t *xid);
 fr_radius_packet_t     *fr_dhcpv4_packet_alloc(uint8_t const *data, ssize_t data_len);
 bool           fr_dhcpv4_is_encodable(void const *item, void const *uctx);