]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add support for nested attributes
authorAlan T. DeKok <aland@freeradius.org>
Fri, 1 Sep 2023 13:47:15 +0000 (09:47 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 1 Sep 2023 17:10:25 +0000 (13:10 -0400)
src/lib/server/packet.c
src/lib/server/packet.h

index f0204c61435983c84036ce8608bfca1c085998a3..ee9061050269b9b13f8cd7f563fefa353dc35db2 100644 (file)
@@ -23,6 +23,7 @@
 RCSID("$Id$")
 
 #include <freeradius-devel/server/packet.h>
+#include <freeradius-devel/util/pair_legacy.h>
 
 static fr_dict_t const *dict_freeradius;
 
@@ -32,16 +33,20 @@ fr_dict_autoload_t util_packet_dict[] = {
        { NULL }
 };
 
-static fr_dict_attr_t const *attr_net_tlv;
+static fr_dict_attr_t const *attr_net;
+static fr_dict_attr_t const *attr_net_src;
 static fr_dict_attr_t const *attr_net_src_ip;
 static fr_dict_attr_t const *attr_net_src_port;
+static fr_dict_attr_t const *attr_net_dst;
 static fr_dict_attr_t const *attr_net_dst_ip;
 static fr_dict_attr_t const *attr_net_dst_port;
 static fr_dict_attr_t const *attr_net_timestamp;
 
 extern fr_dict_attr_autoload_t util_packet_dict_attr[];
 fr_dict_attr_autoload_t util_packet_dict_attr[] = {
-       { .out = &attr_net_tlv, .name = "Net", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
+       { .out = &attr_net, .name = "Net", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
+       { .out = &attr_net_src, .name = "Net.Src", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
+       { .out = &attr_net_dst, .name = "Net.Dst", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
        { .out = &attr_net_src_ip, .name = "Net.Src.IP", .type = FR_TYPE_COMBO_IP_ADDR, .dict = &dict_freeradius },
        { .out = &attr_net_src_port, .name = "Net.Src.Port", .type = FR_TYPE_UINT16, .dict = &dict_freeradius },
        { .out = &attr_net_dst_ip, .name = "Net.Dst.IP", .type = FR_TYPE_COMBO_IP_ADDR, .dict = &dict_freeradius },
@@ -51,6 +56,27 @@ fr_dict_attr_autoload_t util_packet_dict_attr[] = {
        { NULL }
 };
 
+static int inet2pairs(TALLOC_CTX *ctx, fr_pair_list_t *list,
+                     fr_dict_attr_t const *attr_ip, fr_dict_attr_t const *attr_port,
+                     fr_ipaddr_t const *ipaddr, uint16_t port)
+{
+       fr_pair_t *vp;
+
+       vp = fr_pair_afrom_da(ctx, attr_ip);
+       if (!vp) return -1;
+       fr_value_box_ipaddr(&vp->data, attr_ip, ipaddr, false);
+       fr_pair_set_immutable(vp);
+       fr_pair_append(list, vp);
+
+       vp = fr_pair_afrom_da(ctx, attr_port);
+       if (!vp) return -1;
+       vp->vp_uint16 = port;
+       fr_pair_set_immutable(vp);
+       fr_pair_append(list, vp);
+
+       return 0;
+}
+
 /** Allocate a "Net." struct with src/dst host and port.
  *
  * @param      ctx    The context in which the packet is allocated.
@@ -59,73 +85,122 @@ fr_dict_attr_autoload_t util_packet_dict_attr[] = {
  *
  * @return
  *     -  0 on success
- *     - -1 on error.
+ *     - <0 on error.
  */
 int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_radius_packet_t const *packet)
 {
-       fr_pair_t *vp;
+       fr_pair_t *vp, *net, *tlv;
 
        /*
-        *      @todo - create nested ones!
-        *
-        *      We can't call main_config_migrate_option_get(), as this file is also included in radclient. :(
+        *      We overload the pair_legacy_nested flag, as we can't
+        *      call main_config_migrate_option_get(), as this file is
+        *      also included in radclient. :(
         */
-       vp = fr_pair_afrom_da(ctx, attr_net_src_ip);
-       if (!vp) return -1;
-       fr_value_box_ipaddr(&vp->data, attr_net_src_ip, &packet->socket.inet.src_ipaddr, true);
-       fr_pair_append(list, vp);
+       if (!fr_pair_legacy_nested) {
+               if (inet2pairs(ctx, list, attr_net_src_ip, attr_net_src_port, &packet->socket.inet.src_ipaddr, packet->socket.inet.src_port) < 0) return -1;
 
-       vp = fr_pair_afrom_da(ctx, attr_net_src_port);
-       if (!vp) return -1;
-       vp->vp_uint32 = packet->socket.inet.src_port;   
-       fr_pair_append(list, vp);
+               if (inet2pairs(ctx, list, attr_net_dst_ip, attr_net_dst_port, &packet->socket.inet.dst_ipaddr, packet->socket.inet.dst_port) < 0) return -1;
 
-       vp = fr_pair_afrom_da(ctx, attr_net_dst_ip);
-       if (!vp) return -1;
-       fr_value_box_ipaddr(&vp->data, attr_net_dst_ip, &packet->socket.inet.dst_ipaddr, true);
-       fr_pair_append(list, vp);
+               vp = fr_pair_afrom_da(ctx, attr_net_timestamp);
+               if (!vp) return -1;
+               vp->vp_date = fr_time_to_unix_time(packet->timestamp);
+               fr_pair_set_immutable(vp);
+               fr_pair_append(list, vp);
 
-       vp = fr_pair_afrom_da(ctx, attr_net_dst_port);
-       if (!vp) return -1;
-       vp->vp_uint32 = packet->socket.inet.dst_port;   
-       fr_pair_append(list, vp);
+               return 0;
+       }
 
-       vp = fr_pair_afrom_da(ctx, attr_net_timestamp);
+       /*
+        *      Net
+        */
+       net = fr_pair_afrom_da(ctx, attr_net);
+       if (!net) return -1;
+       fr_pair_append(list, net);
+
+       /*
+        *      Net.Src
+        */
+       tlv = fr_pair_afrom_da(net, attr_net_src);
+       if (!tlv) return -1;
+       fr_pair_append(&net->vp_group, tlv);
+
+       if (inet2pairs(tlv, &tlv->vp_group, attr_net_src_ip, attr_net_src_port, &packet->socket.inet.src_ipaddr, packet->socket.inet.src_port) < 0) return -1;
+
+       /*
+        *      Net.Dst
+        */
+       tlv = fr_pair_afrom_da(net, attr_net_dst);
+       if (!tlv) return -1;
+       fr_pair_append(&net->vp_group, tlv);
+       
+       if (inet2pairs(tlv, &tlv->vp_group, attr_net_src_ip, attr_net_src_port, &packet->socket.inet.src_ipaddr, packet->socket.inet.src_port) < 0) return -1;
+
+       /*
+        *      Timestamp
+        */
+       vp = fr_pair_afrom_da(net, attr_net_timestamp);
        if (!vp) return -1;
        vp->vp_date = fr_time_to_unix_time(packet->timestamp);
-       fr_pair_append(list, vp);
+       fr_pair_set_immutable(vp);
+       fr_pair_append(&net->vp_group, vp);
 
        return 0;
 }
 
-int fr_packet_pairs_to_packet(fr_radius_packet_t *packet, fr_pair_list_t const *list)
+static void pairs2inet(fr_ipaddr_t *ipaddr, uint16_t *port, fr_pair_list_t const *list,
+                      fr_dict_attr_t const *attr_ip, fr_dict_attr_t const *attr_port)
 {
        fr_pair_t *vp;
 
+       vp = fr_pair_find_by_da(list, NULL, attr_ip);
+       if (vp) *ipaddr = vp->vp_ip;
+       
+       vp = fr_pair_find_by_da(list, NULL, attr_port);
+       if (vp) *port = vp->vp_uint16;
+}
+
+/** Convert pairs to information in a packet.
+ *
+ * @param packet       the packet to send
+ * @param list         the list to check for Net.*
+ */
+void fr_packet_pairs_to_packet(fr_radius_packet_t *packet, fr_pair_list_t const *list)
+{
+       fr_pair_t *vp, *net, *tlv;
+
        /*
         *      @todo - create nested ones!
         */
-       vp = fr_pair_find_by_da(list, NULL, attr_net_src_ip);
-       if (vp) packet->socket.inet.src_ipaddr = vp->vp_ip;
+       if (!fr_pair_legacy_nested) {
+               pairs2inet(&packet->socket.inet.src_ipaddr, &packet->socket.inet.src_port, list,
+                          attr_net_src_ip, attr_net_src_port);
 
-       vp = fr_pair_find_by_da(list, NULL, attr_net_src_port);
-       if (vp) packet->socket.inet.src_port = vp->vp_uint16;
+               pairs2inet(&packet->socket.inet.dst_ipaddr, &packet->socket.inet.dst_port, list,
+                          attr_net_dst_ip, attr_net_dst_port);
 
-       vp = fr_pair_find_by_da(list, NULL, attr_net_dst_ip);
-       if (vp) packet->socket.inet.dst_ipaddr = vp->vp_ip;
+               vp = fr_pair_find_by_da(list, NULL, attr_net_timestamp);
+               if (vp) packet->timestamp = fr_time_add(packet->timestamp, vp->vp_time_delta);
+       }
 
-       vp = fr_pair_find_by_da(list, NULL, attr_net_dst_port);
-       if (vp) packet->socket.inet.dst_port = vp->vp_uint16;
+       net = fr_pair_find_by_da(list, NULL, attr_net);
+       if (!net) return;
 
-       vp = fr_pair_find_by_da(list, NULL, attr_net_timestamp);
-       if (vp) packet->timestamp = fr_time_add(packet->timestamp, vp->vp_time_delta);
+       tlv = fr_pair_find_by_da(&net->vp_group, NULL, attr_net_src);
+       if (tlv) {
+               pairs2inet(&packet->socket.inet.src_ipaddr, &packet->socket.inet.src_port, &tlv->vp_group,
+                          attr_net_src_ip, attr_net_src_port);
+       }
 
-       return 0;
+       tlv = fr_pair_find_by_da(&net->vp_group, NULL, attr_net_dst);
+       if (tlv) {
+               pairs2inet(&packet->socket.inet.dst_ipaddr, &packet->socket.inet.dst_port, &tlv->vp_group,
+                          attr_net_dst_ip, attr_net_dst_port);
+       }
 }
 
 /** Initialises the Net. packet attributes.
  *
- * @note Call log free when the server is done to fix any spurious memory leaks.
+ * @note Call packet_global_free() when the server is done to avoid leaks.
  * @return
  *     - 0 on success.
  *     - -1 on failure.
index f107d252e7a566321a39b6e0541ce956c41b7b2b..586314913d5e1d2e66886d90b90a7a2e654dec89 100644 (file)
@@ -30,8 +30,8 @@ extern "C" {
 #include <freeradius-devel/util/packet.h>
 #include <freeradius-devel/util/socket.h>
 
-int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_radius_packet_t const *packet);
-int fr_packet_pairs_to_packet(fr_radius_packet_t *packet, fr_pair_list_t const *list);
+int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_radius_packet_t const *packet) CC_HINT(nonnull);
+void fr_packet_pairs_to_packet(fr_radius_packet_t *packet, fr_pair_list_t const *list) CC_HINT(nonnull);
 
 int packet_global_init(void);
 void packet_global_free(void);