Pull up r25660 from trunk
authorTom Yu <tlyu@mit.edu>
Fri, 10 Feb 2012 21:19:07 +0000 (21:19 +0000)
committerTom Yu <tlyu@mit.edu>
Fri, 10 Feb 2012 21:19:07 +0000 (21:19 +0000)
 ------------------------------------------------------------------------
 r25660 | ghudson | 2012-01-26 16:56:16 -0500 (Thu, 26 Jan 2012) | 22 lines

 ticket: 7082
 subject: Various lookaside cache fixes
 target_version: 1.10
 tags: pullup

 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
version_fixed: 1.10.1
status: resolved

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-10@25681 dc483132-0cff-0310-8789-dd5450dbe970

src/kdc/dispatch.c

index 75e6f0a604e0b406420b484dd6b0314a113e1c32..efb54ed649af7a879e138480a943969d64937d2e 100644 (file)
@@ -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;
             }