*** empty log message ***
authorJohn Kohl <jtkohl@mit.edu>
Wed, 13 Feb 1991 15:36:07 +0000 (15:36 +0000)
committerJohn Kohl <jtkohl@mit.edu>
Wed, 13 Feb 1991 15:36:07 +0000 (15:36 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@1688 dc483132-0cff-0310-8789-dd5450dbe970

src/kdc/replay.c [new file with mode: 0644]

diff --git a/src/kdc/replay.c b/src/kdc/replay.c
new file mode 100644 (file)
index 0000000..1c7aff3
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/copyright.h>.
+ *
+ * Replay lookaside cache for the KDC, to avoid extra work.
+ *
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcsid_replay_c[] =
+"$Id$";
+#endif /* !lint & !SABER */
+
+#include <krb5/krb5.h>
+#include <krb5/ext-proto.h>
+#include <krb5/libos-proto.h>
+#include <krb5/kdb.h>
+#include "kdc_util.h"
+
+typedef struct _krb5_kdc_replay_ent {
+    struct _krb5_kdc_replay_ent *next;
+    int num_hits;
+    krb5_int32 timein;
+    krb5_data *req_packet;
+    krb5_data *reply_packet;
+} krb5_kdc_replay_ent;
+
+static krb5_kdc_replay_ent root_ptr = {0};
+
+static int hits = 0;
+static int calls = 0;
+static int max_hits_per_entry = 0;
+static int num_entries = 0;
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#define STALE_TIME     2*60            /* two minutes */
+#define STALE(ptr) (abs((ptr)->timein - timenow) >= STALE_TIME)
+
+#define MATCH(ptr) (((ptr)->req_packet->length == inpkt->length) && \
+                   !memcmp((ptr)->req_packet->data, inpkt->data, inpkt->length))
+
+/* XXX
+   Todo:  quench the size of the queue...
+ */
+
+/* return TRUE if outpkt is filled in with a packet to reply with,
+   FALSE if the caller should do the work */
+
+krb5_boolean
+kdc_check_lookaside(inpkt, outpkt)
+register krb5_data *inpkt;
+register krb5_data **outpkt;
+{
+    krb5_int32 timenow;
+    register krb5_kdc_replay_ent *eptr, *last, *hold;
+
+    if (krb5_timeofday(&timenow))
+       return FALSE;
+
+    calls++;
+
+    /* search for a replay entry in the queue, possibly removing
+       stale entries while we're here */
+
+    if (root_ptr.next) {
+       for (last=&root_ptr, eptr = root_ptr.next;
+            eptr;
+            eptr = eptr->next) {
+           if (MATCH(eptr)) {
+               eptr->num_hits++;
+               hits++;
+
+               if (krb5_copy_data(eptr->reply_packet, outpkt))
+                   return FALSE;
+               else
+                   return TRUE;
+               /* return here, don't bother flushing even if it is stale.
+                  if we just matched, we may get another retransmit... */
+           }
+           if (STALE(eptr)) {
+               /* flush it and collect stats */
+               max_hits_per_entry = max(max_hits_per_entry, eptr->num_hits);
+               krb5_free_data(eptr->req_packet);
+               krb5_free_data(eptr->reply_packet);
+               hold = eptr;
+               last->next = eptr->next;
+               eptr = last;
+               xfree(hold);
+           } else {
+               /* this isn't it, just move along */
+               last = eptr;
+           }
+       }
+    }
+    return FALSE;
+}
+
+/* insert a request & reply into the lookaside queue.  assumes it's not
+   already there, and can fail softly due to other weird errors. */
+
+void
+kdc_insert_lookaside(inpkt, outpkt)
+register krb5_data *inpkt;
+register krb5_data *outpkt;
+{
+    register krb5_kdc_replay_ent *eptr;    
+    krb5_int32 timenow;
+
+    if (krb5_timeofday(&timenow))
+       return;
+
+    /* this is a new entry */
+    eptr = (krb5_kdc_replay_ent *)calloc(1, sizeof(*eptr));
+    if (!eptr)
+       return;
+    eptr->timein = timenow;
+    if (krb5_copy_data(inpkt, &eptr->req_packet)) {
+       xfree(eptr);
+       return;
+    }
+    if (krb5_copy_data(outpkt, &eptr->reply_packet)) {
+       krb5_free_data(eptr->req_packet);
+       xfree(eptr);
+       return;
+    }
+    eptr->next = root_ptr.next;
+    root_ptr.next = eptr;
+    num_entries++;
+    return;
+}