C-API: Added cli_process_control(), added uid to cli_process_control()

This commit is contained in:
Olof hagsand 2023-06-01 17:44:49 +02:00
parent bd6a67f1d9
commit 080eef0278
12 changed files with 103 additions and 20 deletions

View file

@ -54,6 +54,7 @@ Expected: July 2023
### C/CLI-API changes on existing features ### C/CLI-API changes on existing features
Developers may need to change their code Developers may need to change their code
* Added `uid` parameter to `clixon_process_register()`
* Added output function to JSON output: * Added output function to JSON output:
* `xml2json_vec(...,skiptop)` --> `xml2json_vec(..., cligen_output, skiptop)` * `xml2json_vec(...,skiptop)` --> `xml2json_vec(..., cligen_output, skiptop)`
* `yang2cli_yspec` removed last argument `printgen`. * `yang2cli_yspec` removed last argument `printgen`.

View file

@ -314,13 +314,14 @@ restconf_pseudo_process_control(clicon_handle h)
if (clixon_process_register(h, RESTCONF_PROCESS, if (clixon_process_register(h, RESTCONF_PROCESS,
"Clixon RESTCONF process", "Clixon RESTCONF process",
NULL /* XXX network namespace */, NULL /* XXX network namespace */,
-1,
restconf_rpc_wrapper, restconf_rpc_wrapper,
argv, nr) < 0) argv, nr) < 0)
goto done; goto done;
if (argv != NULL)
free(argv);
retval = 0; retval = 0;
done: done:
if (argv != NULL)
free(argv);
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);
return retval; return retval;

View file

@ -1626,3 +1626,64 @@ cvec_append(cvec *cvv0,
} }
return cvv2; return cvv2;
} }
/*! Process control as defined by clixon-lib API
*
* @param[in] h Clicon handle
* @param[in] cvv Not used
* @param[in] arg Two strings: <process name> <process operation>
* @code
* actions-daemon("Actions daemon operations") start,
* cli_process_control("Action process", "start");
* @endcode
*/
int
cli_process_control(clicon_handle h,
cvec *cvv,
cvec *argv)
{
int retval = -1;
char *name;
char *opstr;
cbuf *cb = NULL;
cxobj *xret = NULL;
cxobj *xerr;
if (cvec_len(argv) != 2){
clicon_err(OE_PLUGIN, EINVAL, "Requires two element: process name and operation");
goto done;
}
name = cv_string_get(cvec_i(argv, 0));
opstr = cv_string_get(cvec_i(argv, 1));
if (clixon_process_op_str2int(opstr) == -1){
clicon_err(OE_UNIX, 0, "No such process op: %s", opstr);
goto done;
}
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR);
cprintf(cb, ">");
cprintf(cb, "<process-control xmlns=\"%s\">", CLIXON_LIB_NS);
cprintf(cb, "<name>%s</name>", name);
cprintf(cb, "<operation>%s</operation>", opstr);
cprintf(cb, "</process-control>");
cprintf(cb, "</rpc>");
if (clicon_rpc_netconf(h, cbuf_get(cb), &xret, NULL) < 0)
goto done;
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
clixon_netconf_error(xerr, "Get configuration", NULL);
goto done;
}
if (clixon_xml2file(stdout, xml_child_i(xret, 0), 0, 1, NULL, cligen_output, 0, 1) < 0)
goto done;
retval = 0;
done:
if (xret)
xml_free(xret);
if (cb)
cbuf_free(cb);
return retval;
}

View file

@ -1515,7 +1515,6 @@ cli_show_statistics(clicon_handle h,
if (clixon_xml2file(stdout, xml_child_i(xret, 0), 0, 1, NULL, cligen_output, 0, 1) < 0) if (clixon_xml2file(stdout, xml_child_i(xret, 0), 0, 1, NULL, cligen_output, 0, 1) < 0)
goto done; goto done;
fprintf(stdout, "CLI:\n"); fprintf(stdout, "CLI:\n");
retval = 0; retval = 0;
done: done:
if (xret) if (xret)

View file

@ -80,8 +80,6 @@ int cli_notification_register(clicon_handle h, char *stream, enum format_enum fo
char *filter, int status, char *filter, int status,
int (*fn)(int, void*), void *arg); int (*fn)(int, void*), void *arg);
/* cli_common.c: CLIgen new vector callbacks */
int mtpoint_paths(yang_stmt *yspec0, char *mtpoint, char *api_path_fmt1, char **api_path_fmt01); int mtpoint_paths(yang_stmt *yspec0, char *mtpoint, char *api_path_fmt1, char **api_path_fmt01);
int dbxml_body(cxobj *xbot, cvec *cvv); int dbxml_body(cxobj *xbot, cvec *cvv);
int identityref_add_ns(cxobj *x, void *arg); int identityref_add_ns(cxobj *x, void *arg);
@ -113,6 +111,7 @@ int cli_unlock(clicon_handle h, cvec *cvv, cvec *argv);
int cli_copy_config(clicon_handle h, cvec *cvv, cvec *argv); int cli_copy_config(clicon_handle h, cvec *cvv, cvec *argv);
int cli_help(clicon_handle h, cvec *vars, cvec *argv); int cli_help(clicon_handle h, cvec *vars, cvec *argv);
cvec *cvec_append(cvec *cvv0, cvec *cvv1); cvec *cvec_append(cvec *cvv0, cvec *cvv1);
int cli_process_control(clicon_handle h, cvec *vars, cvec *argv);
/* In cli_show.c */ /* In cli_show.c */
int expand_dbvar(void *h, char *name, cvec *cvv, cvec *argv, int expand_dbvar(void *h, char *name, cvec *cvv, cvec *argv,

View file

@ -52,19 +52,25 @@ typedef enum proc_operation {
PROC_OP_STATUS PROC_OP_STATUS
} proc_operation; } proc_operation;
/* Process RPC callback function */ /*! Process RPC callback function
typedef int (proc_cb_t)(clicon_handle h, process_entry_t *pe, proc_operation *operation); *
* @param[in] h Clixon handle
* @param[in] pe Process entry
* @param[in,out] op Process operation
*/
typedef int (proc_cb_t)(clicon_handle h,
process_entry_t *pe,
proc_operation *operation);
/* /*
* Prototypes * Prototypes
*/ */
int clixon_proc_socket(char **argv, int sock_flags, pid_t *pid, int *sock); int clixon_proc_socket(char **argv, int sock_flags, pid_t *pid, int *sock);
int clixon_proc_socket_close(pid_t pid, int sock); int clixon_proc_socket_close(pid_t pid, int sock);
int clixon_proc_background(char **argv, const char *netns, pid_t *pid);
int clixon_process_pid(clicon_handle h, const char *name, pid_t *pid); int clixon_process_pid(clicon_handle h, const char *name, pid_t *pid);
proc_operation clixon_process_op_str2int(char *opstr); proc_operation clixon_process_op_str2int(char *opstr);
int clixon_process_argv_get(clicon_handle h, const char *name, char ***argv, int *argc); int clixon_process_argv_get(clicon_handle h, const char *name, char ***argv, int *argc);
int clixon_process_register(clicon_handle h, const char *name, const char *descr, const char *netns, proc_cb_t *callback, char **argv, int argc); int clixon_process_register(clicon_handle h, const char *name, const char *descr, const char *netns, uid_t uid, proc_cb_t *callback, char **argv, int argc);
int clixon_process_delete_all(clicon_handle h); int clixon_process_delete_all(clicon_handle h);
int clixon_process_operation(clicon_handle h, const char *name, proc_operation op, const int wrapit); int clixon_process_operation(clicon_handle h, const char *name, proc_operation op, const int wrapit);
int clixon_process_status(clicon_handle h, const char *name, cbuf *cbret); int clixon_process_status(clicon_handle h, const char *name, cbuf *cbret);

View file

@ -243,7 +243,7 @@ clicon_log_str(int level,
char *msg) char *msg)
{ {
if (_logflags & CLICON_LOG_SYSLOG) if (_logflags & CLICON_LOG_SYSLOG)
syslog(LOG_MAKEPRI(LOG_USER, level), "%s", msg); syslog(LOG_MAKEPRI(LOG_USER, level), "%s", msg); // XXX this may block
/* syslog makes own filtering, we do it here: /* syslog makes own filtering, we do it here:
* if normal (not debug) then filter loglevels >= debug * if normal (not debug) then filter loglevels >= debug
*/ */

View file

@ -81,7 +81,7 @@
* @param[in] buf Packet buffer * @param[in] buf Packet buffer
* @param[in] buflen Length of packet buffer * @param[in] buflen Length of packet buffer
* @param[out] eof Socket closed / eof? * @param[out] eof Socket closed / eof?
* @retval 0 OK * @retval n length
* @retval -1 Error * @retval -1 Error
*/ */
ssize_t ssize_t

View file

@ -1688,6 +1688,7 @@ netconf_db_find(cxobj *xn,
* cbuf_free(cb); * cbuf_free(cb);
* @endcode * @endcode
* @see clixon_netconf_error_fn * @see clixon_netconf_error_fn
* XXX does not support prefixes properly
*/ */
int int
netconf_err2cb(cxobj *xerr, netconf_err2cb(cxobj *xerr,

View file

@ -50,7 +50,8 @@
description, namespace, start arguments, etc. Starts in STOPPED state: description, namespace, start arguments, etc. Starts in STOPPED state:
--> STOPPED --> STOPPED
On operation "start" or "restart" it gets a pid and goes into RUNNING state: On operation using clixon_process_operation():
"start" or "restart" it gets a pid and goes into RUNNING state:
STOPPED -- (re)start --> RUNNING(pid) STOPPED -- (re)start --> RUNNING(pid)
When running, several things may happen: When running, several things may happen:
@ -116,6 +117,7 @@
#include "clixon_hash.h" #include "clixon_hash.h"
#include "clixon_handle.h" #include "clixon_handle.h"
#include "clixon_options.h" #include "clixon_options.h"
#include "clixon_uid.h"
#include "clixon_event.h" #include "clixon_event.h"
#include "clixon_sig.h" #include "clixon_sig.h"
#include "clixon_string.h" #include "clixon_string.h"
@ -143,6 +145,7 @@ struct process_entry_t {
char *pe_name; /* Name of process used for internal use. Unique with exiting=0 */ char *pe_name; /* Name of process used for internal use. Unique with exiting=0 */
char *pe_description; /* Description of service */ char *pe_description; /* Description of service */
char *pe_netns; /* Network namespace */ char *pe_netns; /* Network namespace */
uid_t pe_uid; /* UID of process or -1 to keep same as backend */
char **pe_argv; /* argv with command as element 0 and NULL-terminated */ char **pe_argv; /* argv with command as element 0 and NULL-terminated */
int pe_argc; /* Length of argc */ int pe_argc; /* Length of argc */
pid_t pe_pid; /* Running process id (state) or 0 if dead (pid is set if exiting=1) */ pid_t pe_pid; /* Running process id (state) or 0 if dead (pid is set if exiting=1) */
@ -261,13 +264,15 @@ clixon_proc_socket_close(pid_t pid,
* *
* @param[in] argv NULL-terminated Argument vector * @param[in] argv NULL-terminated Argument vector
* @param[in] netns Network namespace (or NULL) * @param[in] netns Network namespace (or NULL)
* @param[in] uid User-id or -1 to keep existing
* @param[out] pid Process id * @param[out] pid Process id
* @retval 0 OK * @retval 0 OK
* @retval -1 Error. * @retval -1 Error.
*/ */
int static int
clixon_proc_background(char **argv, clixon_proc_background(char **argv,
const char *netns, const char *netns,
uid_t uid,
pid_t *pid0) pid_t *pid0)
{ {
int retval = -1; int retval = -1;
@ -308,10 +313,14 @@ clixon_proc_background(char **argv,
char nsfile[PATH_MAX]; char nsfile[PATH_MAX];
int nsfd; int nsfd;
#endif #endif
if (uid != -1){
if (drop_priv_perm(uid) < 0)
goto done;
}
clicon_debug(1, "%s child", __FUNCTION__); clicon_debug(1, "%s child", __FUNCTION__);
clicon_signal_unblock(0); clicon_signal_unblock(0);
signal(SIGTSTP, SIG_IGN); signal(SIGTSTP, SIG_IGN);
if (chdir("/") < 0){ if (chdir("/") < 0){
clicon_err(OE_UNIX, errno, "chdirq"); clicon_err(OE_UNIX, errno, "chdirq");
exit(1); exit(1);
@ -425,6 +434,7 @@ clixon_process_argv_get(clicon_handle h,
* @param[in] name Process name * @param[in] name Process name
* @param[in] description Description of process * @param[in] description Description of process
* @param[in] netns Namespace netspace (or NULL) * @param[in] netns Namespace netspace (or NULL)
* @param[in] uid UID of process (or -1 to keep same)
* @param[in] callback Wrapper function * @param[in] callback Wrapper function
* @param[in] argv NULL-terminated vector of vectors * @param[in] argv NULL-terminated vector of vectors
* @param[in] argc Length of argv * @param[in] argc Length of argv
@ -437,6 +447,7 @@ clixon_process_register(clicon_handle h,
const char *name, const char *name,
const char *description, const char *description,
const char *netns, const char *netns,
const uid_t uid,
proc_cb_t *callback, proc_cb_t *callback,
char **argv, char **argv,
int argc) int argc)
@ -470,6 +481,7 @@ clixon_process_register(clicon_handle h,
clicon_err(OE_DB, errno, "strdup netns"); clicon_err(OE_DB, errno, "strdup netns");
goto done; goto done;
} }
pe->pe_uid = uid;
pe->pe_argc = argc; pe->pe_argc = argc;
if ((pe->pe_argv = calloc(argc, sizeof(char *))) == NULL){ if ((pe->pe_argv = calloc(argc, sizeof(char *))) == NULL){
clicon_err(OE_UNIX, errno, "calloc"); clicon_err(OE_UNIX, errno, "calloc");
@ -839,7 +851,8 @@ clixon_process_sched(int fd,
if (proc_op_run(pe->pe_pid, &isrunning) < 0) if (proc_op_run(pe->pe_pid, &isrunning) < 0)
goto done; goto done;
if (!isrunning) if (!isrunning)
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0) if (clixon_proc_background(pe->pe_argv, pe->pe_netns,
pe->pe_uid, &pe->pe_pid) < 0)
goto done; goto done;
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__, clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
pe->pe_name, pe->pe_pid, pe->pe_name, pe->pe_pid,
@ -864,7 +877,8 @@ clixon_process_sched(int fd,
case PROC_OP_START: case PROC_OP_START:
if (isrunning) /* Already runs */ if (isrunning) /* Already runs */
break; break;
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0) if (clixon_proc_background(pe->pe_argv, pe->pe_netns,
pe->pe_uid, &pe->pe_pid) < 0)
goto done; goto done;
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__, clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
pe->pe_name, pe->pe_pid, pe->pe_name, pe->pe_pid,
@ -967,7 +981,8 @@ clixon_process_waitpid(clicon_handle h)
case PROC_OP_RESTART: case PROC_OP_RESTART:
/* This is the case where there is an existing process running. /* This is the case where there is an existing process running.
* it was killed above but still runs and needs to be reaped */ * it was killed above but still runs and needs to be reaped */
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0) if (clixon_proc_background(pe->pe_argv, pe->pe_netns,
pe->pe_uid, &pe->pe_pid) < 0)
goto done; goto done;
gettimeofday(&pe->pe_starttime, NULL); gettimeofday(&pe->pe_starttime, NULL);
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__, clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,