newvector should be a bool
[freeradius.git] / src / main / process.c
index af867f3..0150a1c 100644 (file)
@@ -108,7 +108,16 @@ static char const *child_state_names[REQUEST_CHILD_NUM_STATES] = {
                fr_event_insert(el, request_timer, request, \
                                &when, &request->ev);
 
-
+/*
+ *     We need a different VERIFY_REQUEST macro in process.c
+ *     To avoid the race conditions with the master thread
+ *     checking the REQUEST whilst it's being worked on by
+ *     the child.
+ */
+#if defined(WITH_VERIFY_PTR) && defined(HAVE_PTHREAD_H)
+#  undef VERIFY_REQUEST
+#  define VERIFY_REQUEST(_x) if (pthread_equal(pthread_self(), _x->child_pid) != 0) verify_request(__FILE__, __LINE__, _x)
+#endif
 
 /**
  * @section request_timeline
@@ -345,9 +354,9 @@ static void tv_add(struct timeval *tv, int usec_delay)
 }
 
 /*
- *     In daemon mode, AND this request has debug flags set.
+ *     Debug the packet if requested.
  */
-#define DEBUG_PACKET if (!debug_flag && request->log.lvl && request->log.func) debug_packet
+#define DEBUG_PACKET if (request->log.lvl && request->log.func) debug_packet
 
 static void debug_packet(REQUEST *request, RADIUS_PACKET *packet, int direction)
 {
@@ -411,29 +420,60 @@ static void debug_packet(REQUEST *request, RADIUS_PACKET *packet, int direction)
 
 static struct timeval *request_response_window(REQUEST *request)
 {
-       /*
-        *      The client hasn't set the response window.  Return
-        *      either the home server one, if set, or the global one.
-        */
-       if (!timerisset(&request->client->response_window)) {
-               return &request->home_server->response_window;
-       }
+       VERIFY_REQUEST(request);
+
+       if (request->client) {
+               /*
+                *      The client hasn't set the response window.  Return
+                *      either the home server one, if set, or the global one.
+                */
+               if (!timerisset(&request->client->response_window)) {
+                       return &request->home_server->response_window;
+               }
 
-       if (timercmp(&request->client->response_window,
-                    &request->home_server->response_window, <)) {
-               return &request->client->response_window;
+               if (timercmp(&request->client->response_window,
+                            &request->home_server->response_window, <)) {
+                       return &request->client->response_window;
+               }
        }
 
+       rad_assert(request->home_server != NULL);
        return &request->home_server->response_window;
 }
 
 /*
+ * Determine initial request processing delay.
+ */
+static int request_init_delay(REQUEST *request)
+{
+       struct timeval half_response_window;
+
+       VERIFY_REQUEST(request);
+
+       /* Allow client response window to lower initial delay */
+       if (timerisset(&request->client->response_window)) {
+               half_response_window.tv_sec = request->client->response_window.tv_sec >> 1;
+               half_response_window.tv_usec =
+                       ((request->client->response_window.tv_sec & 1) * USEC +
+                               request->client->response_window.tv_usec) >> 1;
+               if (timercmp(&half_response_window, &request->root->init_delay, <))
+                       return (int)half_response_window.tv_sec * USEC +
+                               (int)half_response_window.tv_usec;
+       }
+
+       return (int)request->root->init_delay.tv_sec * USEC +
+               (int)request->root->init_delay.tv_usec;
+}
+
+/*
  *     Callback for ALL timer events related to the request.
  */
 static void request_timer(void *ctx)
 {
-       REQUEST *request = ctx;
-       int action = request->timer_action;
+       REQUEST *request = talloc_get_type_abort(ctx, REQUEST);
+       int action;
+
+       action = request->timer_action;
 
        TRACE_STATE_MACHINE;
 
@@ -450,6 +490,8 @@ STATE_MACHINE_DECL(request_done)
        char buffer[128];
 #endif
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
 #ifdef WITH_COA
@@ -689,7 +731,7 @@ STATE_MACHINE_DECL(request_done)
 
        if (request->ev) fr_event_delete(el, &request->ev);
 
-       request_free(&request);
+       talloc_free(request);
 }
 
 
@@ -697,6 +739,8 @@ static void request_cleanup_delay_init(REQUEST *request, struct timeval const *p
 {
        struct timeval now, when;
 
+       VERIFY_REQUEST(request);
+
        if (request->packet->code == PW_CODE_ACCOUNTING_REQUEST) goto done;
 
        if (!request->root->cleanup_delay) goto done;
@@ -745,6 +789,8 @@ static void request_process_timer(REQUEST *request)
        int action = FR_ACTION_TIMER;
 #endif
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -958,6 +1004,8 @@ static void request_queue_or_run(UNUSED REQUEST *request,
        int action = FR_ACTION_TIMER;
 #endif
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        /*
@@ -984,7 +1032,7 @@ static void request_queue_or_run(UNUSED REQUEST *request,
                /*
                 *      (re) set the initial delay.
                 */
-               request->delay = (main_config.init_delay.tv_sec * USEC) + main_config.init_delay.tv_usec;
+               request->delay = request_init_delay(request);
                if (request->delay > USEC) request->delay = USEC;
                gettimeofday(&when, NULL);
                tv_add(&when, request->delay);
@@ -1028,6 +1076,8 @@ STATE_MACHINE_DECL(request_common)
        char buffer[128];
 #endif
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -1092,6 +1142,8 @@ STATE_MACHINE_DECL(request_cleanup_delay)
 {
        struct timeval when;
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -1132,6 +1184,8 @@ STATE_MACHINE_DECL(request_cleanup_delay)
 
 STATE_MACHINE_DECL(request_response_delay)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -1160,10 +1214,12 @@ STATE_MACHINE_DECL(request_response_delay)
 
 static int CC_HINT(nonnull) request_pre_handler(REQUEST *request, UNUSED int action)
 {
-       TRACE_STATE_MACHINE;
-
        int rcode;
 
+       VERIFY_REQUEST(request);
+
+       TRACE_STATE_MACHINE;
+
        if (request->master_state == REQUEST_STOP_PROCESSING) return 0;
 
        /*
@@ -1214,6 +1270,8 @@ STATE_MACHINE_DECL(request_finish)
 {
        VALUE_PAIR *vp;
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        (void) action;  /* -Wunused */
@@ -1263,16 +1321,16 @@ STATE_MACHINE_DECL(request_finish)
        /*
         *      Catch Auth-Type := Reject BEFORE proxying the packet.
         */
-       else if (request->packet->code == PW_CODE_AUTHENTICATION_REQUEST) {
+       else if (request->packet->code == PW_CODE_ACCESS_REQUEST) {
                if (request->reply->code == 0) {
                        vp = pairfind(request->config_items, PW_AUTH_TYPE, 0, TAG_ANY);
 
-                       if (!vp || (vp->vp_integer != PW_CODE_AUTHENTICATION_REJECT)) {
+                       if (!vp || (vp->vp_integer != PW_CODE_ACCESS_REJECT)) {
                                RDEBUG2("There was no response configured: "
                                        "rejecting request");
                        }
 
-                       request->reply->code = PW_CODE_AUTHENTICATION_REJECT;
+                       request->reply->code = PW_CODE_ACCESS_REJECT;
                }
        }
 
@@ -1284,7 +1342,7 @@ STATE_MACHINE_DECL(request_finish)
        if (vp) pairadd(&request->reply->vps, vp);
 
        switch (request->reply->code) {
-       case PW_CODE_AUTHENTICATION_ACK:
+       case PW_CODE_ACCESS_ACCEPT:
                rad_postauth(request);
                break;
        case PW_CODE_ACCESS_CHALLENGE:
@@ -1305,7 +1363,7 @@ STATE_MACHINE_DECL(request_finish)
         *      We do this separately so ACK and challenge can change the code
         *      to reject if a module returns reject.
         */
-       if (request->reply->code == PW_CODE_AUTHENTICATION_REJECT) {
+       if (request->reply->code == PW_CODE_ACCESS_REJECT) {
                pairdelete(&request->config_items, PW_POST_AUTH_TYPE, 0, TAG_ANY);
                vp = pairmake_config("Post-Auth-Type", "Reject", T_OP_SET);
                if (vp) rad_postauth(request);
@@ -1342,7 +1400,7 @@ STATE_MACHINE_DECL(request_finish)
        /*
         *      See if we need to delay an Access-Reject packet.
         */
-       if ((request->reply->code == PW_CODE_AUTHENTICATION_REJECT) &&
+       if ((request->reply->code == PW_CODE_ACCESS_REJECT) &&
            (request->root->reject_delay > 0)) {
                request->response_delay = request->root->reject_delay;
 
@@ -1394,6 +1452,8 @@ STATE_MACHINE_DECL(request_finish)
 
 STATE_MACHINE_DECL(request_running)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -1491,6 +1551,8 @@ int request_receive(rad_listen_t *listener, RADIUS_PACKET *packet,
        struct timeval now;
        listen_socket_t *sock = NULL;
 
+       VERIFY_PACKET(packet);
+
        /*
         *      Set the last packet received.
         */
@@ -1531,7 +1593,7 @@ int request_receive(rad_listen_t *listener, RADIUS_PACKET *packet,
 
 #ifdef WITH_STATS
                                switch (packet->code) {
-                               case PW_CODE_AUTHENTICATION_REQUEST:
+                               case PW_CODE_ACCESS_REQUEST:
                                        FR_STATS_INC(auth, total_dup_requests);
                                        break;
 
@@ -1642,7 +1704,7 @@ skip_dup:
                } else {
                        RDEBUG("Not sending reply");
                }
-               request_free(&request);
+               talloc_free(request);
                return 1;
        }
 
@@ -1665,10 +1727,10 @@ static REQUEST *request_setup(rad_listen_t *listener, RADIUS_PACKET *packet,
         *      Create and initialize the new request.
         */
        request = request_alloc(NULL);
-       request->reply = rad_alloc(request, 0);
+       request->reply = rad_alloc(request, false);
        if (!request->reply) {
                ERROR("No memory");
-               request_free(&request);
+               talloc_free(request);
                return NULL;
        }
 
@@ -1690,7 +1752,7 @@ static REQUEST *request_setup(rad_listen_t *listener, RADIUS_PACKET *packet,
 
 #ifdef WITH_STATS
        request->listener->stats.last_packet = request->packet->timestamp.tv_sec;
-       if (packet->code == PW_CODE_AUTHENTICATION_REQUEST) {
+       if (packet->code == PW_CODE_ACCESS_REQUEST) {
                request->client->auth.last_packet = request->packet->timestamp.tv_sec;
                radius_auth_stats.last_packet = request->packet->timestamp.tv_sec;
 #ifdef WITH_ACCOUNTING
@@ -1761,7 +1823,7 @@ static REQUEST *request_setup(rad_listen_t *listener, RADIUS_PACKET *packet,
  */
 static void tcp_socket_timer(void *ctx)
 {
-       rad_listen_t *listener = ctx;
+       rad_listen_t *listener = talloc_get_type_abort(ctx, rad_listen_t);
        listen_socket_t *sock = listener->data;
        struct timeval end, now;
        char buffer[256];
@@ -1875,7 +1937,7 @@ static void add_jitter(struct timeval *when)
  */
 static int eol_proxy_listener(void *ctx, void *data)
 {
-       rad_listen_t *this = ctx;
+       rad_listen_t *this = talloc_get_type_abort(ctx, rad_listen_t);
        RADIUS_PACKET **proxy_p = data;
        REQUEST *request;
 
@@ -1904,7 +1966,7 @@ static int eol_proxy_listener(void *ctx, void *data)
 
 static int eol_listener(void *ctx, void *data)
 {
-       rad_listen_t *this = ctx;
+       rad_listen_t *this = talloc_get_type_abort(ctx, rad_listen_t);
        RADIUS_PACKET **packet_p = data;
        REQUEST *request;
 
@@ -1929,6 +1991,8 @@ static int eol_listener(void *ctx, void *data)
  */
 static void remove_from_proxy_hash_nl(REQUEST *request, bool yank)
 {
+       VERIFY_REQUEST(request);
+
        if (!request->in_proxy_hash) return;
 
        fr_packet_list_id_free(proxy_list, request->proxy, yank);
@@ -1972,6 +2036,8 @@ static void remove_from_proxy_hash_nl(REQUEST *request, bool yank)
 
 static void remove_from_proxy_hash(REQUEST *request)
 {
+       VERIFY_REQUEST(request);
+
        /*
         *      Check this without grabbing the mutex because it's a
         *      lot faster that way.
@@ -2001,6 +2067,8 @@ static int insert_into_proxy_hash(REQUEST *request)
        int rcode, tries;
        void *proxy_listener;
 
+       VERIFY_REQUEST(request);
+
        rad_assert(request->proxy != NULL);
        rad_assert(request->home_server != NULL);
        rad_assert(proxy_list != NULL);
@@ -2113,6 +2181,8 @@ static int process_proxy_reply(REQUEST *request, RADIUS_PACKET *reply)
        int post_proxy_type = 0;
        VALUE_PAIR *vp;
 
+       VERIFY_REQUEST(request);
+
        /*
         *      There may be a proxy reply, but it may be too late.
         */
@@ -2134,7 +2204,7 @@ static int process_proxy_reply(REQUEST *request, RADIUS_PACKET *reply)
         *      post-proxy-type Reject
         */
        if (!vp && reply &&
-           reply->code == PW_CODE_AUTHENTICATION_REJECT) {
+           reply->code == PW_CODE_ACCESS_REJECT) {
                DICT_VALUE      *dval;
 
                dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Reject");
@@ -2153,6 +2223,7 @@ static int process_proxy_reply(REQUEST *request, RADIUS_PACKET *reply)
        }
 
        if (reply) {
+               VERIFY_PACKET(reply);
                /*
                 *      Decode the packet.
                 */
@@ -2231,6 +2302,8 @@ int request_proxy_reply(RADIUS_PACKET *packet)
        struct timeval now;
        char buffer[128];
 
+       VERIFY_PACKET(packet);
+
        PTHREAD_MUTEX_LOCK(&proxy_mutex);
        proxy_p = fr_packet_list_find_byreply(proxy_list, packet);
 
@@ -2313,13 +2386,14 @@ int request_proxy_reply(RADIUS_PACKET *packet)
         */
        if (request->home_server->state == HOME_STATE_UNKNOWN) {
                request->home_server->state = HOME_STATE_ALIVE;
+               request->home_server->response_timeouts = 0;
        }
 
 #ifdef WITH_STATS
        request->home_server->stats.last_packet = packet->timestamp.tv_sec;
        request->proxy_listener->stats.last_packet = packet->timestamp.tv_sec;
 
-       if (request->proxy->code == PW_CODE_AUTHENTICATION_REQUEST) {
+       if (request->proxy->code == PW_CODE_ACCESS_REQUEST) {
                proxy_auth_stats.last_packet = packet->timestamp.tv_sec;
 #ifdef WITH_ACCOUNTING
        } else if (request->proxy->code == PW_CODE_ACCOUNTING_REQUEST) {
@@ -2354,7 +2428,9 @@ static int setup_post_proxy_fail(REQUEST *request)
        DICT_VALUE const *dval = NULL;
        VALUE_PAIR *vp;
 
-       if (request->proxy->code == PW_CODE_AUTHENTICATION_REQUEST) {
+       VERIFY_REQUEST(request);
+
+       if (request->proxy->code == PW_CODE_ACCESS_REQUEST) {
                dval = dict_valbyname(PW_POST_PROXY_TYPE, 0,
                                      "Fail-Authentication");
 
@@ -2390,6 +2466,8 @@ static int setup_post_proxy_fail(REQUEST *request)
 
 STATE_MACHINE_DECL(proxy_no_reply)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -2415,6 +2493,8 @@ STATE_MACHINE_DECL(proxy_no_reply)
 
 STATE_MACHINE_DECL(proxy_running)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -2449,6 +2529,8 @@ static int request_will_proxy(REQUEST *request)
        REALM *realm = NULL;
        home_pool_t *pool = NULL;
 
+       VERIFY_REQUEST(request);
+
        if (!request->root->proxy_requests) return 0;
        if (request->packet->dst_port == 0) return 0;
        if (request->packet->code == PW_CODE_STATUS_SERVER) return 0;
@@ -2473,7 +2555,7 @@ static int request_will_proxy(REQUEST *request)
                /*
                 *      Figure out which pool to use.
                 */
-               if (request->packet->code == PW_CODE_AUTHENTICATION_REQUEST) {
+               if (request->packet->code == PW_CODE_ACCESS_REQUEST) {
                        pool = realm->auth_pool;
 
 #ifdef WITH_ACCOUNTING
@@ -2498,7 +2580,7 @@ static int request_will_proxy(REQUEST *request)
                if (!vp) return 0;
 
                switch (request->packet->code) {
-               case PW_CODE_AUTHENTICATION_REQUEST:
+               case PW_CODE_ACCESS_REQUEST:
                        pool_type = HOME_TYPE_AUTH;
                        break;
 
@@ -2600,7 +2682,7 @@ static int request_will_proxy(REQUEST *request)
         *      since we can't use the request authenticator
         *      anymore - we changed it.
         */
-       if ((request->packet->code == PW_CODE_AUTHENTICATION_REQUEST) &&
+       if ((request->packet->code == PW_CODE_ACCESS_REQUEST) &&
            pairfind(request->proxy->vps, PW_CHAP_PASSWORD, 0, TAG_ANY) &&
            pairfind(request->proxy->vps, PW_CHAP_CHALLENGE, 0, TAG_ANY) == NULL) {
                vp = radius_paircreate(request->proxy, &request->proxy->vps, PW_CHAP_CHALLENGE, 0);
@@ -2678,6 +2760,8 @@ static int request_proxy(REQUEST *request, int retransmit)
 {
        char buffer[128];
 
+       VERIFY_REQUEST(request);
+
        rad_assert(request->parent == NULL);
        rad_assert(request->home_server != NULL);
 
@@ -2740,7 +2824,7 @@ static int request_proxy(REQUEST *request, int retransmit)
                request->proxy_reply = talloc_steal(request, fake->reply);
                fake->reply = NULL;
 
-               request_free(&fake);
+               talloc_free(fake);
 
                /*
                 *      Just do the work here, rather than trying to
@@ -2809,6 +2893,8 @@ static int request_proxy_anew(REQUEST *request)
 {
        home_server_t *home;
 
+       VERIFY_REQUEST(request);
+
        /*
         *      Delete the request from the proxy list.
         *
@@ -2879,6 +2965,8 @@ STATE_MACHINE_DECL(request_ping)
        home_server_t *home = request->home_server;
        char buffer[128];
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -2929,6 +3017,7 @@ STATE_MACHINE_DECL(request_ping)
                 *      pings.
                 */
                home->state = HOME_STATE_ALIVE;
+               home->response_timeouts = 0;
                exec_trigger(request, home->cs, "home_server.alive", false);
                home->currently_outstanding = 0;
                home->num_sent_pings = 0;
@@ -2960,7 +3049,7 @@ STATE_MACHINE_DECL(request_ping)
  */
 static void ping_home_server(void *ctx)
 {
-       home_server_t *home = ctx;
+       home_server_t *home = talloc_get_type_abort(ctx, home_server_t);
        REQUEST *request;
        VALUE_PAIR *vp;
        struct timeval when, now;
@@ -2991,7 +3080,7 @@ static void ping_home_server(void *ctx)
        request->number = request_num_counter++;
        NO_CHILD_THREAD;
 
-       request->proxy = rad_alloc(request, 1);
+       request->proxy = rad_alloc(request, true);
        rad_assert(request->proxy != NULL);
 
        if (home->ping_check == HOME_PING_CHECK_STATUS_SERVER) {
@@ -3001,7 +3090,7 @@ static void ping_home_server(void *ctx)
                         "Message-Authenticator", "0x00", T_OP_SET);
 
        } else if (home->type == HOME_TYPE_AUTH) {
-               request->proxy->code = PW_CODE_AUTHENTICATION_REQUEST;
+               request->proxy->code = PW_CODE_ACCESS_REQUEST;
 
                pairmake(request->proxy, &request->proxy->vps,
                         "User-Name", home->ping_user_name, T_OP_SET);
@@ -3062,7 +3151,7 @@ static void ping_home_server(void *ctx)
                rad_assert(!request->in_request_hash);
                rad_assert(!request->in_proxy_hash);
                rad_assert(request->ev == NULL);
-               request_free(&request);
+               talloc_free(request);
                return;
        }
 
@@ -3167,7 +3256,7 @@ static void mark_home_server_zombie(home_server_t *home, struct timeval *now, st
 
 void revive_home_server(void *ctx)
 {
-       home_server_t *home = ctx;
+       home_server_t *home = talloc_get_type_abort(ctx, home_server_t);
        char buffer[128];
 
 #ifdef WITH_TCP
@@ -3175,6 +3264,7 @@ void revive_home_server(void *ctx)
 #endif
 
        home->state = HOME_STATE_ALIVE;
+       home->response_timeouts = 0;
        home_trigger(home, "home_server.alive");
        home->currently_outstanding = 0;
        gettimeofday(&home->revive_time, NULL);
@@ -3244,6 +3334,8 @@ STATE_MACHINE_DECL(proxy_wait_for_reply)
        home_server_t *home = request->home_server;
        char buffer[128];
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        rad_assert(request->packet->code != PW_CODE_STATUS_SERVER);
@@ -3399,7 +3491,9 @@ STATE_MACHINE_DECL(proxy_wait_for_reply)
                    && (home->proto != IPPROTO_TCP)
 #endif
                        ) {
-                       mark_home_server_zombie(home, &now, response_window);
+                       home->response_timeouts++;
+                       if (home->response_timeouts >= home->max_response_timeouts)
+                               mark_home_server_zombie(home, &now, response_window);
                }
 
                FR_STATS_TYPE_INC(home->stats.total_timeouts);
@@ -3476,7 +3570,8 @@ static void request_coa_originate(REQUEST *request)
        fr_ipaddr_t ipaddr;
        char buffer[256];
 
-       rad_assert(request != NULL);
+       VERIFY_REQUEST(request);
+
        rad_assert(request->coa != NULL);
        rad_assert(request->proxy == NULL);
        rad_assert(!request->in_proxy_hash);
@@ -3493,7 +3588,7 @@ static void request_coa_originate(REQUEST *request)
        if (vp) {
                if (vp->vp_integer == 0) {
                fail:
-                       request_free(&request->coa);
+                       TALLOC_FREE(request->coa);
                        return;
                }
        }
@@ -3685,6 +3780,8 @@ static void coa_timer(REQUEST *request)
        uint32_t delay, frac;
        struct timeval now, when, mrd;
 
+       VERIFY_REQUEST(request);
+
        rad_assert(request->parent == NULL);
 
        if (request->proxy_reply) return request_process_timer(request);
@@ -3806,6 +3903,8 @@ STATE_MACHINE_DECL(coa_wait_for_reply)
 {
        rad_assert(request->parent == NULL);
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -3832,6 +3931,9 @@ static void request_coa_separate(REQUEST *request)
 #ifdef DEBUG_STATE_MACHINE
        int action = FR_ACTION_TIMER;
 #endif
+
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        rad_assert(request->parent != NULL);
@@ -3856,6 +3958,8 @@ STATE_MACHINE_DECL(coa_no_reply)
 {
        char buffer[128];
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -3887,6 +3991,8 @@ STATE_MACHINE_DECL(coa_no_reply)
 
 STATE_MACHINE_DECL(coa_running)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -3927,7 +4033,7 @@ STATE_MACHINE_DECL(coa_running)
  ***********************************************************************/
 static void event_socket_handler(UNUSED fr_event_list_t *xel, UNUSED int fd, void *ctx)
 {
-       rad_listen_t *listener = ctx;
+       rad_listen_t *listener = talloc_get_type_abort(ctx, rad_listen_t);
 
        rad_assert(xel == el);
 
@@ -3959,7 +4065,7 @@ static void event_socket_handler(UNUSED fr_event_list_t *xel, UNUSED int fd, voi
 static void event_poll_detail(void *ctx)
 {
        int delay;
-       rad_listen_t *this = ctx;
+       rad_listen_t *this = talloc_get_type_abort(ctx, rad_listen_t);
        struct timeval when, now;
        listen_detail_t *detail = this->data;
 
@@ -4035,7 +4141,7 @@ static void event_status(struct timeval *wake)
 #ifdef WITH_TCP
 static void listener_free_cb(void *ctx)
 {
-       rad_listen_t *this = ctx;
+       rad_listen_t *this = talloc_get_type_abort(ctx, rad_listen_t);
        char buffer[1024];
 
        if (this->count > 0) {
@@ -4546,13 +4652,15 @@ int radius_event_start(CONF_SECTION *cs, bool have_children)
 
        time(&fr_start_time);
 
-       /*
-        *  radius_event_init() must be called first
-        */
-       rad_assert(el);
+       if (!check_config) {
+               /*
+                *  radius_event_init() must be called first
+                */
+               rad_assert(el);
 
-       pl = fr_packet_list_create(0);
-       if (!pl) return 0;      /* leak el */
+               pl = fr_packet_list_create(0);
+               if (!pl) return 0;      /* leak el */
+       }
 
        request_num_counter = 0;
 
@@ -4572,6 +4680,17 @@ int radius_event_start(CONF_SECTION *cs, bool have_children)
                        fr_exit(1);
                }
 #endif
+
+               /*
+                *      The "init_delay" is set to "response_window".
+                *      Reset it to half of "response_window" in order
+                *      to give the event loop enough time to service
+                *      the event before hitting "response_window".
+                */
+               main_config.init_delay.tv_usec += (main_config.init_delay.tv_sec & 0x01) * USEC;
+               main_config.init_delay.tv_usec >>= 1;
+               main_config.init_delay.tv_sec >>= 1;
+
        }
 #endif
 
@@ -4668,6 +4787,8 @@ static int proxy_delete_cb(UNUSED void *ctx, void *data)
 {
        REQUEST *request = fr_packet2myptr(REQUEST, proxy, data);
 
+       VERIFY_REQUEST(request);
+
        request->master_state = REQUEST_STOP_PROCESSING;
 
 #ifdef HAVE_PTHREAD_H
@@ -4700,6 +4821,8 @@ static int request_delete_cb(UNUSED void *ctx, void *data)
 {
        REQUEST *request = fr_packet2myptr(REQUEST, packet, data);
 
+       VERIFY_REQUEST(request);
+
        request->master_state = REQUEST_STOP_PROCESSING;
 
        /*
@@ -4730,7 +4853,7 @@ static int request_delete_cb(UNUSED void *ctx, void *data)
        }
 #endif
 
-       request_free(&request);
+       talloc_free(request);
 
        /*
         *      Delete it from the list, and continue;