From 548f8461c75c5638f0c24ca86364a17f59619b89 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Thu, 26 Jan 2012 21:56:16 +0000 Subject: Various lookaside cache fixes Don't touch the lookaside cache if we're responding with a lookaside cache entry. Also, leave the null entry behind if we're deliberately dropping a request (a rare case) so that we don't have to process it again. Fixes several lookaside problems in 1.10: * When dropping a request because it was already being processed, we were erroneously removing the null entry, causing us to process the request again upon a second retransmit. * When responding to a finished request with a lookaside entry, we were removing and re-adding the entry to the cache, resetting its time and performing unnecessary work. * We were not caching responses we couldn't deliver because they were too big for UDP, causing us to re-process the request when it came in again via TCP instead of simply delivering the cached response. ticket: 7082 target_version: 1.10 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25660 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kdc/dispatch.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'src/kdc/dispatch.c') diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c index b4c02f3247..efe7098814 100644 --- a/src/kdc/dispatch.c +++ b/src/kdc/dispatch.c @@ -44,20 +44,11 @@ struct dispatch_state { }; static void -finish_dispatch(void *arg, krb5_error_code code, krb5_data *response) +finish_dispatch(struct dispatch_state *state, krb5_error_code code, + krb5_data *response) { - struct dispatch_state *state = arg; - loop_respond_fn oldrespond; - void *oldarg; - - assert(state); - oldrespond = state->respond; - oldarg = state->arg; - -#ifndef NOCACHE - /* Remove our NULL cache entry to indicate request completion. */ - kdc_remove_lookaside(kdc_context, state->request); -#endif + loop_respond_fn oldrespond = state->respond; + void *oldarg = state->arg; if (state->is_tcp == 0 && response && response->length > max_dgram_reply_size) { @@ -70,14 +61,27 @@ finish_dispatch(void *arg, krb5_error_code code, krb5_data *response) error_message(code)); } + free(state); + (*oldrespond)(oldarg, code, response); +} + +static void +finish_dispatch_cache(void *arg, krb5_error_code code, krb5_data *response) +{ + struct dispatch_state *state = arg; + #ifndef NOCACHE - /* put the response into the lookaside buffer */ - else if (!code && response) + /* Remove the null cache entry unless we actually want to discard this + * request. */ + if (code != KRB5KDC_ERR_DISCARD) + kdc_remove_lookaside(kdc_context, state->request); + + /* Put the response into the lookaside buffer (if we produced one). */ + if (code == 0 && response != NULL) kdc_insert_lookaside(state->request, response); #endif - free(state); - (*oldrespond)(oldarg, code, response); + finish_dispatch(state, code, response); } void @@ -167,7 +171,7 @@ dispatch(void *cb, struct sockaddr *local_saddr, * process_as_req frees the request if it is called */ if (!(retval = setup_server_realm(as_req->server))) { - process_as_req(as_req, pkt, from, vctx, finish_dispatch, + process_as_req(as_req, pkt, from, vctx, finish_dispatch_cache, state); return; } -- cgit