]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
generalize handling of conflicting packets
authorAlan T. DeKok <aland@freeradius.org>
Wed, 17 Jan 2018 21:17:02 +0000 (16:17 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 17 Jan 2018 22:23:51 +0000 (17:23 -0500)
src/modules/proto_radius/proto_radius_udp.c

index 36d85dcd7c8c6b85027bda3255ab2caadfec142e..28e1ddaee8fde8c3c06fa0ebd77e7bc46422225e 100644 (file)
@@ -155,6 +155,7 @@ typedef struct proto_radius_udp_t {
 
 typedef struct dynamic_packet_t {
        uint8_t                 *packet;
+       fr_time_t               timestamp;
        fr_tracking_entry_t     *track;
        fr_dlist_t              entry;
 } dynamic_packet_t;
@@ -409,8 +410,9 @@ static ssize_t dynamic_client_packet_restore(proto_radius_udp_t *inst, uint8_t *
        dynamic_packet_t        *saved;
        size_t                  packet_len;
 
+redo:
        entry = FR_DLIST_FIRST(inst->dynamic_clients.packets);
-       if (!entry) return -1;
+       if (!entry) return 0;
        fr_dlist_remove(entry);
 
        saved = fr_ptr_to_type(dynamic_packet_t, entry, entry);
@@ -418,6 +420,17 @@ static ssize_t dynamic_client_packet_restore(proto_radius_udp_t *inst, uint8_t *
        rad_assert(saved->packet != NULL);
        rad_assert(saved->track != NULL);
 
+       /*
+        *      The saved packet subsequently got a conflicting
+        *      packet.  We therefore ignore the older one.
+        */
+       if (saved->timestamp != saved->track->timestamp) {
+       drop_packet:
+               ((proto_radius_udp_address_t *)saved->track->src_dst)->client->received--;
+               talloc_free(saved);
+               goto redo;
+       }
+
        /*
         *      Can't copy the packet over, there's nothing more we
         *      can do.
@@ -425,8 +438,7 @@ static ssize_t dynamic_client_packet_restore(proto_radius_udp_t *inst, uint8_t *
        packet_len = talloc_array_length(saved->packet);
        if (packet_len > buffer_len) {
                (void) fr_radius_tracking_entry_delete(inst->ft, saved->track);
-               talloc_free(saved);
-               return -1;
+               goto drop_packet;
        }
 
        /*
@@ -498,6 +510,7 @@ static int dynamic_client_packet_save(proto_radius_udp_t *inst, uint8_t *packet,
        MEM(saved = talloc_zero(inst, dynamic_packet_t));
        MEM(saved->packet = talloc_memdup(saved, packet, packet_len));
        saved->track = *track;
+       saved->timestamp = saved->track->timestamp;
        fr_dlist_insert_tail(&address->client->packets, &saved->entry);
 
        ((proto_radius_udp_address_t *)saved->track->src_dst)->client->received++;
@@ -543,6 +556,7 @@ static ssize_t dynamic_client_alloc(proto_radius_udp_t *inst, uint8_t *packet, s
 
        client->ipaddr = address->src_ipaddr;
        client->src_ipaddr = address->dst_ipaddr;
+
        client->network = *network;
 
        address->client = client;
@@ -847,10 +861,7 @@ static ssize_t mod_read(void *instance, void **packet_ctx, fr_time_t **recv_time
        entry = FR_DLIST_FIRST(inst->dynamic_clients.packets);
        if (entry) {
                data_size = dynamic_client_packet_restore(inst, buffer, buffer_len, &track);
-               if (data_size < 0) {
-                       rad_assert(0 == 1);
-                       return 0;
-               }
+               if (!data_size) goto do_read;
 
                packet_len = data_size;
 
@@ -1384,25 +1395,6 @@ static ssize_t mod_write(void *instance, void *packet_ctx,
                        rad_assert(newclient->negative == false);
                }
 
-               /*
-                *      This particular packet had a later one
-                *      over-ride it.  We still add the client, but
-                *      don't send the packet on towards mod_read()
-                */
-               if (track->timestamp != request_time) {
-                       DEBUG3("First packet was too late, discarding it.");
-
-                       entry = FR_DLIST_FIRST(client->packets);
-                       rad_assert(entry != NULL);
-                       saved = fr_ptr_to_type(dynamic_packet_t, entry, entry);
-
-                       fr_dlist_remove(&saved->entry);
-                       /* leave the tracking table entry - it's used by a later packet */
-                       rad_assert(saved->track == track);
-                       talloc_free(saved);
-                       inst->dynamic_clients.num_pending_packets--;
-               }
-
                /*
                 *      Move the packets over to the pending list, and
                 *      re-write their client pointers to be the newly