]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Simple RADIUS packet tracking API
authorAlan T. DeKok <aland@freeradius.org>
Sun, 20 Nov 2016 02:49:39 +0000 (21:49 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 20 Nov 2016 14:56:21 +0000 (09:56 -0500)
src/util/all.mk
src/util/track.c [new file with mode: 0644]
src/util/track.h [new file with mode: 0644]

index 97fe97b80f7f4ca253e17f67aba47fa510a93fc2..4a918beceec198ecf4863e2ad89a138e8750b67b 100644 (file)
@@ -1,6 +1,6 @@
 TARGET := libfreeradius-util.a
 
-SOURCES        :=      ring_buffer.c message.c atomic_queue.c queue.c time.c channel.c
+SOURCES        :=      ring_buffer.c message.c atomic_queue.c queue.c time.c channel.c track.c
 
 TGT_PREREQS    := libfreeradius-radius.la
 TGT_LDLIBS     := $(LIBS)
diff --git a/src/util/track.c b/src/util/track.c
new file mode 100644 (file)
index 0000000..2f1e835
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * track.c     RADIUS packet tracking
+ *
+ * Version:    $Id$
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2016  Alan DeKok <aland@freeradius.org>
+ */
+RCSID("$Id$")
+
+#include <freeradius-devel/util/track.h>
+
+/*
+ *     RADIUS-specific tracking table.
+ *
+ *     It's a fixed-size array of 256 entries, indexed by ID.  Which
+ *     means we don't need to store ID in the table.  We also don't
+ *     need to store the packet type, as we assume that we have a
+ *     unique tracking table per packet type.
+ */
+
+struct fr_tracking_t {
+       int             num_entries;    //!< number of used entries.
+
+       fr_tracking_entry_t packet[256];
+};
+
+/** Create a tracking table for one type of RADIUS packets.
+ *
+ * @param[in] ctx the talloc ctx
+ * @return
+ *     - NULL on error
+ *     - fr_tracking_t * on success
+ */
+fr_tracking_t *fr_radius_tracking_create(TALLOC_CTX *ctx)
+{
+       fr_tracking_t *ft;
+
+       if (!ctx) return NULL;
+
+       ft = talloc_zero(ctx, fr_tracking_t);
+       if (!ft) return NULL;
+
+       ft->num_entries = 0;
+       return ft;
+}
+
+/** Delete an entry from the tracking table.
+ *
+ * @param[in] ft the tracking table
+ * @param[in] id the ID of the entry to delete
+ * @return
+ *     - <0 on error
+ *     - 0 on success
+ */
+int fr_radius_tracking_entry_delete(fr_tracking_t *ft, uint8_t id)
+{
+       fr_tracking_entry_t *entry;
+
+#ifndef NDEBUG
+       (void) talloc_get_type_abort(ft, fr_tracking_t);
+#endif
+       entry = &ft->packet[id];
+       if (entry->timestamp == 0) return -1;
+
+       entry->timestamp = 0;
+       ft->num_entries--;
+
+       return 0;
+}
+
+/** Insert a (possibly new) packet and a timestamp
+ *
+ * @param[in] ft the tracking table
+ * @param[in] packet the RADIUS packet to insert
+ * @param[in] timestamp when this packet was received
+ * @param[out] p_entry pointer to newly inserted entry.
+ * @return
+ *     - FR_TRACKING_UNUSED, there was an error inserting the element
+ *     - FR_TRACKING_NEW, a new entry was created
+ *     - FR_TRACKING_SAME, the packet is the same as one already in the tracking table
+ *     - FR_TRACKING_DIFFERENT, the old packet was deleted, and the newer packet inserted
+ */
+fr_tracking_status_t fr_radius_tracking_entry_insert(fr_tracking_t *ft, uint8_t *packet, fr_time_t timestamp,
+                                                    fr_tracking_entry_t **p_entry)
+{
+       fr_tracking_entry_t *entry;
+
+#ifndef NDEBUG
+       (void) talloc_get_type_abort(ft, fr_tracking_t);
+#endif
+
+       entry = &ft->packet[packet[1]];
+
+       /*
+        *      The entry is unused, insert it.
+        */
+       if (entry->timestamp == 0) {
+               entry->timestamp = timestamp;
+               memcpy(&entry->data[0], packet + 2, 18);
+               *p_entry = entry;
+
+               ft->num_entries++;
+               return FR_TRACKING_NEW;
+       }
+
+       /*
+        *      Is it the same packet?  If so, return that.
+        */
+       if (memcmp(packet + 2, &entry->data[0], 18) == 0) {
+               *p_entry = entry;
+               return FR_TRACKING_SAME;
+       }
+
+       /*
+        *      It's in use, but the new packet is different.  update
+        *      the timestamp, so that anyone checking it knows it's
+        *      no longer relevant.
+        */
+       entry->timestamp = timestamp;
+
+       /*
+        *      Copy the new packet over top of the old one.
+        */
+       memcpy(&entry->data[0], packet + 2, 18);
+       *p_entry = entry;
+
+       return FR_TRACKING_DIFFERENT;
+}
diff --git a/src/util/track.h b/src/util/track.h
new file mode 100644 (file)
index 0000000..b75032e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#ifndef _FR_TRACK_H
+#define _FR_TRACK_H
+/**
+ * $Id$
+ *
+ * @file util/track.h
+ * @brief RADIUS packet tracking.
+ *
+ * @copyright 2016 Alan DeKok <aland@freeradius.org>
+ */
+RCSIDH(track_h, "$Id$")
+
+#include <freeradius-devel/util/time.h>
+#include <talloc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct fr_tracking_t fr_tracking_t;
+
+/**
+ *  An entry for the tracking table.  It contains the minimum
+ *  information required to track RADIUS packets.
+ */
+typedef struct fr_tracking_entry_t {
+       fr_time_t       timestamp;      //!< when received
+       uint8_t         data[18];       //!< 2 byte length + authentication vector
+} fr_tracking_entry_t;
+
+/**
+ *  The status of an insert.
+ */
+typedef enum fr_tracking_status_t {
+       FR_TRACKING_UNUSED = 0,
+       FR_TRACKING_NEW,
+       FR_TRACKING_SAME,
+       FR_TRACKING_DIFFERENT,
+} fr_tracking_status_t;
+
+fr_tracking_t *fr_radius_tracking_create(TALLOC_CTX *ctx);
+int fr_radius_tracking_entry_delete(fr_tracking_t *ft, uint8_t id) CC_HINT(nonnull);
+fr_tracking_status_t fr_radius_tracking_entry_insert(fr_tracking_t *ft, uint8_t *packet, fr_time_t timestamp,
+                                                    fr_tracking_entry_t **p_entry) CC_HINT(nonnull);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FR_TRACK_H */