static fr_io_final_t mod_process(UNUSED void const *instance, REQUEST *request, fr_io_action_t action) { rlm_rcode_t rcode; CONF_SECTION *unlang; REQUEST_VERIFY(request); /* * Pass this through asynchronously to the module which * is waiting for something to happen. */ if (action != FR_IO_ACTION_RUN) { unlang_signal(request, (fr_state_signal_t) action); return FR_IO_DONE; } switch (request->request_state) { case REQUEST_INIT: request->component = "radius"; unlang = cf_section_find(request->server_cs, "new", "client"); if (!unlang) { RWDEBUG("Failed to find 'new client' section"); request->reply->code = FR_CODE_ACCESS_REJECT; goto send_reply; } RDEBUG("Running 'new client' from file %s", cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP, UNLANG_TOP_FRAME); request->request_state = REQUEST_RECV; /* FALL-THROUGH */ case REQUEST_RECV: rcode = unlang_interpret_resume(request); if (request->master_state == REQUEST_STOP_PROCESSING) return FR_IO_DONE; if (rcode == RLM_MODULE_YIELD) return FR_IO_YIELD; rad_assert(request->log.unlang_indent == 0); switch (rcode) { case RLM_MODULE_OK: case RLM_MODULE_UPDATED: request->reply->code = FR_CODE_ACCESS_ACCEPT; break; case RLM_MODULE_FAIL: case RLM_MODULE_HANDLED: request->reply->code = 0; /* don't reply */ break; default: case RLM_MODULE_REJECT: request->reply->code = FR_CODE_ACCESS_REJECT; break; } unlang = cf_section_find(request->server_cs, "add", "client"); if (!unlang) goto send_reply; rerun_nak: RDEBUG("Running '%s client' from file %s", cf_section_name1(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP, UNLANG_TOP_FRAME); request->request_state = REQUEST_SEND; /* FALL-THROUGH */ case REQUEST_SEND: rcode = unlang_interpret_resume(request); if (request->master_state == REQUEST_STOP_PROCESSING) return FR_IO_DONE; if (rcode == RLM_MODULE_YIELD) return FR_IO_YIELD; rad_assert(request->log.unlang_indent == 0); switch (rcode) { case RLM_MODULE_NOOP: case RLM_MODULE_OK: case RLM_MODULE_UPDATED: case RLM_MODULE_HANDLED: /* reply is already set */ break; default: /* * If we over-ride an ACK with a NAK, run * the NAK section. */ if (request->reply->code != FR_CODE_ACCESS_REJECT) { RWDEBUG("Failed running 'add client', trying 'deny client'."); deny: request->reply->code = FR_CODE_ACCESS_REJECT; unlang = cf_section_find(request->server_cs, "deny", "client"); if (unlang) goto rerun_nak; RWDEBUG("Not running 'deny client' section as it does not exist"); } break; } if (request->reply->code == FR_CODE_ACCESS_ACCEPT) { VALUE_PAIR *vp; vp = fr_pair_find_by_da(request->control, attr_freeradius_client_ip_address, TAG_ANY); if (!vp) fr_pair_find_by_da(request->control, attr_freeradius_client_ipv6_address, TAG_ANY); if (!vp) fr_pair_find_by_da(request->control, attr_freeradius_client_ip_prefix, TAG_ANY); if (!vp) fr_pair_find_by_da(request->control, attr_freeradius_client_ipv6_prefix, TAG_ANY); if (!vp) { ERROR("The 'control' list MUST contain a FreeRADIUS-Client.. IP address attribute"); goto deny; } vp = fr_pair_find_by_da(request->control, attr_freeradius_client_secret, TAG_ANY); if (!vp) { ERROR("The 'control' list MUST contain a FreeRADIUS-Client-Secret attribute"); goto deny; } /* * Else we're flexible. */ } send_reply: /* * This is an internally generated request. Don't print IP addresses. */ if (request->reply->code == FR_CODE_ACCESS_ACCEPT) { RDEBUG("Adding client"); } else { RDEBUG("Denying client"); } break; default: return FR_IO_FAIL; } return FR_IO_REPLY; }
static fr_io_final_t mod_process(UNUSED void const *instance, REQUEST *request, fr_io_action_t action) { VALUE_PAIR *vp; rlm_rcode_t rcode; CONF_SECTION *unlang; REQUEST_VERIFY(request); /* * Pass this through asynchronously to the module which * is waiting for something to happen. */ if (action != FR_IO_ACTION_RUN) { unlang_signal(request, (fr_state_signal_t) action); return FR_IO_DONE; } switch (request->request_state) { case REQUEST_INIT: RDEBUG("Received %s ID %i", fr_dict_enum_alias_by_value(attr_packet_type, fr_box_uint32(request->reply->code)), request->packet->id); log_request_pair_list(L_DBG_LVL_1, request, request->packet->vps, ""); request->component = "radius"; unlang = cf_section_find(request->server_cs, "recv", NULL); if (!unlang) { REDEBUG("Failed to find 'recv' section"); return FR_IO_FAIL; } RDEBUG("Running 'recv' from file %s", cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP, UNLANG_TOP_FRAME); request->request_state = REQUEST_RECV; /* FALL-THROUGH */ case REQUEST_RECV: rcode = unlang_interpret_continue(request); if (request->master_state == REQUEST_STOP_PROCESSING) return FR_IO_DONE; if (rcode == RLM_MODULE_YIELD) return FR_IO_YIELD; rad_assert(request->log.unlang_indent == 0); switch (rcode) { /* * The module has a number of OK return codes. */ case RLM_MODULE_OK: case RLM_MODULE_UPDATED: switch (request->packet->code) { case FR_CODE_ACCOUNTING_REQUEST: request->reply->code = FR_CODE_ACCOUNTING_RESPONSE; break; case FR_CODE_COA_REQUEST: request->reply->code = FR_CODE_COA_ACK; break; case FR_CODE_DISCONNECT_REQUEST: request->reply->code = FR_CODE_DISCONNECT_ACK; break; default: request->reply->code = 0; break; } break; case RLM_MODULE_HANDLED: break; /* * The module failed, or said the request is * invalid, therefore we stop here. */ case RLM_MODULE_NOOP: case RLM_MODULE_FAIL: case RLM_MODULE_INVALID: case RLM_MODULE_NOTFOUND: case RLM_MODULE_REJECT: case RLM_MODULE_USERLOCK: default: request->reply->code = 0; break; } /* * Allow for over-ride of reply code. */ vp = fr_pair_find_by_da(request->reply->vps, attr_packet_type, TAG_ANY); if (vp) request->reply->code = vp->vp_uint32; if (request->reply->code == FR_CODE_DO_NOT_RESPOND) { RWARN("Ignoring 'do_not_respond' as it does not apply to detail files"); } unlang = cf_section_find(request->server_cs, "send", "ok"); if (!unlang) goto send_reply; RDEBUG("Running 'send %s { ... }' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP, UNLANG_TOP_FRAME); request->request_state = REQUEST_SEND; /* FALL-THROUGH */ case REQUEST_SEND: rcode = unlang_interpret_continue(request); if (request->master_state == REQUEST_STOP_PROCESSING) return FR_IO_DONE; if (rcode == RLM_MODULE_YIELD) return FR_IO_YIELD; rad_assert(request->log.unlang_indent == 0); switch (rcode) { case RLM_MODULE_NOOP: case RLM_MODULE_OK: case RLM_MODULE_UPDATED: case RLM_MODULE_HANDLED: /* reply is already set */ break; default: request->reply->code = 0; break; } send_reply: /* * Failed, but we still reply with a magic code, * so that the reader can retransmit. */ if (!request->reply->code) { REDEBUG("Failed ID %i", request->reply->id); } else { RDEBUG("Sent %s ID %i", fr_dict_enum_alias_by_value(attr_packet_type, fr_box_uint32(request->reply->code)), request->reply->id); } log_request_proto_pair_list(L_DBG_LVL_1, request, request->reply->vps, ""); break; default: return FR_IO_FAIL; } return FR_IO_REPLY; }