From: John Kohl Date: Wed, 13 Feb 1991 15:36:07 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: krb5-1.0-alpha4~284 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ab76ffa0d87e489c981a83340abd0fda9b34df99;p=krb5.git *** empty log message *** git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@1688 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/kdc/replay.c b/src/kdc/replay.c new file mode 100644 index 000000000..1c7aff352 --- /dev/null +++ b/src/kdc/replay.c @@ -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 + * . + * + * 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 +#include +#include +#include +#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; +}