/** Sends a request to a RADIUS server and waits for the reply * * @param rh a handle to parsed configuration * @param data a pointer to a SEND_DATA structure * @param msg must be an array of %PW_MAX_MSG_SIZE or NULL; will contain the concatenation of * any %PW_REPLY_MESSAGE received. * @param type must be %AUTH or %ACCT * @return OK_RC (0) on success, TIMEOUT_RC on timeout REJECT_RC on acess reject, or negative * on failure as return value. */ int rc_send_server(rc_handle * rh, SEND_DATA * data, char *msg, rc_type type) { return rc_send_server_ctx(rh, NULL, data, msg, type); }
/** Builds an authentication/accounting request for port id client_port with the value_pairs send and submits it to a specified server. * This function keeps its state in ctx after a successful operation. It can be deallocated using * rc_aaa_ctx_free(). * * @param rh a handle to parsed configuration. * @param ctx if non-NULL it will contain the context of the request; Its initial value should be NULL and it must be released using rc_aaa_ctx_free(). * @param aaaserver a non-NULL SERVER to send the message to. * @param client_port the client port number to use (may be zero to use any available). * @param send a VALUE_PAIR array of values (e.g., PW_USER_NAME). * @param received an allocated array of received values. * @param msg must be an array of PW_MAX_MSG_SIZE or NULL; will contain the concatenation of any * PW_REPLY_MESSAGE received. * @param add_nas_port if non-zero it will include PW_NAS_PORT in sent pairs. * @param request_type one of standard RADIUS codes (e.g., PW_ACCESS_REQUEST). * @return received value_pairs in received, messages from the server in msg and OK_RC (0) on success, negative * on failure as return value. */ int rc_aaa_ctx_server(rc_handle *rh, RC_AAA_CTX **ctx, SERVER *aaaserver, rc_type type, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, int add_nas_port, rc_standard_codes request_type) { SEND_DATA data; VALUE_PAIR *adt_vp = NULL; int result; int timeout = rc_conf_int(rh, "radius_timeout"); int retries = rc_conf_int(rh, "radius_retries"); double start_time = 0; double now = 0; time_t dtime; int servernum; data.send_pairs = send; data.receive_pairs = NULL; /* * if there is more than zero servers, then divide waiting time * among all the servers. */ if(aaaserver->max > 0) { if(timeout > 0) { timeout = (timeout+1) / aaaserver->max; } if(retries > 0) { retries = (retries+1) / aaaserver->max; } } if (add_nas_port != 0 && rc_avpair_get(data.send_pairs, PW_NAS_PORT, 0) == NULL) { /* * Fill in NAS-Port */ if (rc_avpair_add(rh, &(data.send_pairs), PW_NAS_PORT, &client_port, 0, 0) == NULL) return ERROR_RC; } if (request_type == PW_ACCOUNTING_REQUEST) { /* * Fill in Acct-Delay-Time */ dtime = 0; now = rc_getctime(); adt_vp = rc_avpair_get(data.send_pairs, PW_ACCT_DELAY_TIME, 0); if (adt_vp == NULL) { adt_vp = rc_avpair_add(rh, &(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, 0); if (adt_vp == NULL) return ERROR_RC; start_time = now; } else { start_time = now - adt_vp->lvalue; } } if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } servernum=0; do { rc_buildreq(rh, &data, request_type, aaaserver->name[servernum], aaaserver->port[servernum], aaaserver->secret[servernum], timeout, retries); if (request_type == PW_ACCOUNTING_REQUEST) { dtime = rc_getctime() - start_time; rc_avpair_assign(adt_vp, &dtime, 0); } result = rc_send_server_ctx (rh, ctx, &data, msg, type); if (request_type != PW_ACCOUNTING_REQUEST) { *received = data.receive_pairs; } else { rc_avpair_free(data.receive_pairs); } if(result == OK_RC) { DEBUG(LOG_INFO, "servernum %u returned success", servernum); return result; } //rc_log(LOG_ERR, // "servernum %u returned error: %d", servernum, result); servernum++; } while(servernum < aaaserver->max && result == TIMEOUT_RC); return result; }