int pr_get_registered_actions(pr_ctrls_t *ctrl, int flags) { ctrls_action_t *act = NULL; /* Are ctrls blocked? */ if (ctrls_blocked) { errno = EPERM; return -1; } for (act = ctrls_action_list; act; act = act->next) { switch (flags) { case CTRLS_GET_ACTION_ALL: pr_ctrls_add_response(ctrl, "%s (mod_%s.c)", act->action, act->module->name); break; case CTRLS_GET_ACTION_ENABLED: if (act->flags & PR_CTRLS_ACT_DISABLED) break; pr_ctrls_add_response(ctrl, "%s (mod_%s.c)", act->action, act->module->name); break; case CTRLS_GET_DESC: pr_ctrls_add_response(ctrl, "%s: %s", act->action, act->desc); break; } } return 0; }
static int dso_handle_lsmod(pr_ctrls_t *ctrl, int reqargc, char **reqargv) { module *m; /* Check the ACL. */ if (!pr_ctrls_check_acl(ctrl, dso_acttab, "lsmod")) { /* Access denied. */ pr_ctrls_add_response(ctrl, "access denied"); return -1; } if (reqargc != 0) { pr_ctrls_add_response(ctrl, "wrong number of parameters"); return -1; } /* We want to show the modules as `proftpd -l` shows them, in module * load order. So first we find the end of the loaded_modules list, * then walk it backwards. */ for (m = loaded_modules; m && m->next; m = m->next); pr_ctrls_add_response(ctrl, "Loaded Modules:"); for (; m; m = m->prev) pr_ctrls_add_response(ctrl, " mod_%s.c", m->name); return 0; }
static int dynmasq_handle_dynmasq(pr_ctrls_t *ctrl, int reqargc, char **reqargv) { /* Sanity check */ if (reqargc == 0 || reqargv == NULL) { pr_ctrls_add_response(ctrl, "dynmasq: missing required parameters"); return -1; } if (strcmp(reqargv[0], "refresh") == 0) { /* Check the ACLs. */ if (!pr_ctrls_check_acl(ctrl, dynmasq_acttab, "refresh")) { pr_ctrls_add_response(ctrl, "access denied"); return -1; } return dynmasq_handle_refresh(ctrl, --reqargc, ++reqargv); } pr_ctrls_add_response(ctrl, "dynmasq: unknown dynmasq action: '%s'", reqargv[0]); return -1; }
static int dso_handle_insmod(pr_ctrls_t *ctrl, int reqargc, char **reqargv) { register unsigned int i; /* Check the ACL. */ if (!pr_ctrls_check_acl(ctrl, dso_acttab, "insmod")) { /* Access denied. */ pr_ctrls_add_response(ctrl, "access denied"); return -1; } /* Sanity check */ if (reqargc == 0 || reqargv == NULL) { pr_ctrls_add_response(ctrl, "missing required parameters"); return -1; } for (i = 0; i < reqargc; i++) { if (dso_load_module(reqargv[i]) < 0) { /* Make the error messages a little more relevant. */ switch (errno) { case EINVAL: pr_ctrls_add_response(ctrl, "error loading '%s': Bad module name", reqargv[i]); break; case EEXIST: pr_ctrls_add_response(ctrl, "error loading '%s': Already loaded", reqargv[i]); break; default: pr_ctrls_add_response(ctrl, "error loading '%s': %s", reqargv[i], strerror(errno)); break; } } else pr_ctrls_add_response(ctrl, "'%s' loaded", reqargv[i]); } return 0; }
static int dso_handle_rmmod(pr_ctrls_t *ctrl, int reqargc, char **reqargv) { register unsigned int i; /* Check the ACL. */ if (!pr_ctrls_check_acl(ctrl, dso_acttab, "rmmod")) { /* Access denied. */ pr_ctrls_add_response(ctrl, "access denied"); return -1; } /* Sanity check */ if (reqargc == 0 || reqargv == NULL) { pr_ctrls_add_response(ctrl, "missing required parameters"); return -1; } for (i = 0; i < reqargc; i++) { if (dso_unload_module_by_name(reqargv[i]) < 0) { switch (errno) { case EINVAL: pr_ctrls_add_response(ctrl, "error unloading '%s': Bad module name", reqargv[i]); break; case ENOENT: pr_ctrls_add_response(ctrl, "error unloading '%s': Module not loaded", reqargv[i]); break; default: pr_ctrls_add_response(ctrl, "error unloading '%s': %s", reqargv[i], strerror(errno)); break; } } else pr_ctrls_add_response(ctrl, "'%s' unloaded", reqargv[i]); } return 0; }
static int dynmasq_handle_refresh(pr_ctrls_t *ctrl, int reqargc, char **reqargv) { dynmasq_refresh(); pr_ctrls_add_response(ctrl, "dynmasq: refreshed"); return 0; }
int pr_run_ctrls(module *mod, const char *action) { pr_ctrls_t *ctrl = NULL; /* Are ctrls blocked? */ if (ctrls_blocked) { errno = EPERM; return -1; } for (ctrl = ctrls_active_list; ctrl; ctrl = ctrl->ctrls_next) { /* Be watchful of the various client-side flags. Note: if * ctrl->ctrls_cl is ever NULL, it means there's a bug in the code. */ if (ctrl->ctrls_cl->cl_flags != PR_CTRLS_CL_HAVEREQ) continue; /* Has this control been disabled? */ if (ctrl->ctrls_flags & PR_CTRLS_ACT_DISABLED) continue; /* Is it time to trigger this ctrl? */ if (!(ctrl->ctrls_flags & PR_CTRLS_REQUESTED)) continue; if (ctrl->ctrls_when > time(NULL)) { ctrl->ctrls_flags |= PR_CTRLS_PENDING; pr_ctrls_add_response(ctrl, "request pending"); continue; } if (action && strcmp(ctrl->ctrls_action, action) == 0) { pr_log_debug(DEBUG7, "calling '%s' control handler", ctrl->ctrls_action); /* Invoke the callback, if the ctrl's action matches. Unblock * ctrls before invoking the callback, then re-block them after the * callback returns. This will allow the action handlers to use some * of the Controls API functions correctly. */ pr_unblock_ctrls(); ctrl->ctrls_cb_retval = ctrl->ctrls_cb(ctrl, (ctrl->ctrls_cb_args ? ctrl->ctrls_cb_args->nelts : 0), (ctrl->ctrls_cb_args ? (char **) ctrl->ctrls_cb_args->elts : NULL)); pr_block_ctrls(); if (ctrl->ctrls_cb_retval < 1) { ctrl->ctrls_flags &= ~PR_CTRLS_REQUESTED; ctrl->ctrls_flags &= ~PR_CTRLS_PENDING; ctrl->ctrls_flags |= PR_CTRLS_HANDLED; } } else if (!action) { pr_log_debug(DEBUG5, "calling '%s' control handler", ctrl->ctrls_action); /* If no action was given, invoke every callback */ pr_unblock_ctrls(); ctrl->ctrls_cb_retval = ctrl->ctrls_cb(ctrl, (ctrl->ctrls_cb_args ? ctrl->ctrls_cb_args->nelts : 0), (ctrl->ctrls_cb_args ? (char **) ctrl->ctrls_cb_args->elts : NULL)); pr_block_ctrls(); if (ctrl->ctrls_cb_retval < 1) { ctrl->ctrls_flags &= ~PR_CTRLS_REQUESTED; ctrl->ctrls_flags &= ~PR_CTRLS_PENDING; ctrl->ctrls_flags |= PR_CTRLS_HANDLED; } } } return 0; }