Simpler VERIFY_REQUEST macro in process.c
[freeradius.git] / src / main / process.c
index 60cdadc..ba3e52e 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,19 +420,24 @@ 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 (timercmp(&request->client->response_window,
-                    &request->home_server->response_window, <)) {
-               return &request->client->response_window;
+       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;
+               }
        }
 
+       rad_assert(request->home_server != NULL);
        return &request->home_server->response_window;
 }
 
@@ -434,6 +448,8 @@ 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;
@@ -454,8 +470,10 @@ static int request_init_delay(REQUEST *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;
 
@@ -472,6 +490,8 @@ STATE_MACHINE_DECL(request_done)
        char buffer[128];
 #endif
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
 #ifdef WITH_COA
@@ -719,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;
@@ -767,6 +789,8 @@ static void request_process_timer(REQUEST *request)
        int action = FR_ACTION_TIMER;
 #endif
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -980,6 +1004,8 @@ static void request_queue_or_run(UNUSED REQUEST *request,
        int action = FR_ACTION_TIMER;
 #endif
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        /*
@@ -1050,6 +1076,8 @@ STATE_MACHINE_DECL(request_common)
        char buffer[128];
 #endif
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -1114,6 +1142,8 @@ STATE_MACHINE_DECL(request_cleanup_delay)
 {
        struct timeval when;
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -1154,6 +1184,8 @@ STATE_MACHINE_DECL(request_cleanup_delay)
 
 STATE_MACHINE_DECL(request_response_delay)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
        ASSERT_MASTER;
 
@@ -1182,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;
 
        /*
@@ -1236,6 +1270,8 @@ STATE_MACHINE_DECL(request_finish)
 {
        VALUE_PAIR *vp;
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        (void) action;  /* -Wunused */
@@ -1285,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;
                }
        }
 
@@ -1306,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:
@@ -1327,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);
@@ -1364,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;
 
@@ -1416,6 +1452,8 @@ STATE_MACHINE_DECL(request_finish)
 
 STATE_MACHINE_DECL(request_running)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -1513,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.
         */
@@ -1553,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;
 
@@ -1712,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
@@ -1783,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];
@@ -1897,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;
 
@@ -1926,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;
 
@@ -1951,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);
@@ -1994,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.
@@ -2023,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);
@@ -2135,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.
         */
@@ -2156,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");
@@ -2175,6 +2223,7 @@ static int process_proxy_reply(REQUEST *request, RADIUS_PACKET *reply)
        }
 
        if (reply) {
+               VERIFY_PACKET(reply);
                /*
                 *      Decode the packet.
                 */
@@ -2253,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);
 
@@ -2342,7 +2393,7 @@ int request_proxy_reply(RADIUS_PACKET *packet)
        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) {
@@ -2377,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");
 
@@ -2413,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) {
@@ -2438,6 +2493,8 @@ STATE_MACHINE_DECL(proxy_no_reply)
 
 STATE_MACHINE_DECL(proxy_running)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -2472,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;
@@ -2496,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
@@ -2521,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;
 
@@ -2623,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);
@@ -2701,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);
 
@@ -2832,6 +2893,8 @@ static int request_proxy_anew(REQUEST *request)
 {
        home_server_t *home;
 
+       VERIFY_REQUEST(request);
+
        /*
         *      Delete the request from the proxy list.
         *
@@ -2902,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;
 
@@ -2984,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;
@@ -3025,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);
@@ -3191,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
@@ -3269,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);
@@ -3503,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);
@@ -3712,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);
@@ -3833,6 +3903,8 @@ STATE_MACHINE_DECL(coa_wait_for_reply)
 {
        rad_assert(request->parent == NULL);
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -3859,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);
@@ -3883,6 +3958,8 @@ STATE_MACHINE_DECL(coa_no_reply)
 {
        char buffer[128];
 
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -3914,6 +3991,8 @@ STATE_MACHINE_DECL(coa_no_reply)
 
 STATE_MACHINE_DECL(coa_running)
 {
+       VERIFY_REQUEST(request);
+
        TRACE_STATE_MACHINE;
 
        switch (action) {
@@ -3954,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);
 
@@ -3986,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;
 
@@ -4062,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) {
@@ -4708,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
@@ -4740,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;
 
        /*