diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92cf17ee..3d0fb14a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -64,6 +64,11 @@ Users may have to change how they access the system
* Fixed: Configure option `CLICON_RESTCONF_PRETTY` was marked as obsolete but was still used.
* `CLICON_RESTCONF_PRETTY` is now obsolete for sure
* Instead restconf/pretty is used with API function restconf_pretty_get()
+ * Fixed: Configure option `CLICON_RESTCONF_PATH` was marked as obsolete but was still used.
+ * `CLICON_RESTCONF_PATH` is now obsolete for sure
+ * Instead if you use fgci/nginx:
+ * Use `restconf/fcgi-socket`
+ * Ensure `clixon-restconf:fcgi` is set
### Minor features
diff --git a/apps/restconf/restconf_handle.c b/apps/restconf/restconf_handle.c
index 8bf57f1f..45696646 100644
--- a/apps/restconf/restconf_handle.c
+++ b/apps/restconf/restconf_handle.c
@@ -94,6 +94,7 @@ struct restconf_handle {
clicon_hash_t *rh_params; /* restconf parameters, including http headers */
clixon_auth_type_t rh_auth_type; /* authentication type */
int rh_pretty; /* pretty-print for http replies */
+ char *rh_fcgi_socket; /* if-feature fcgi, XXX: use WITH_RESTCONF_FCGI ? */
};
/*! Creates and returns a clicon config handle for other CLICON API calls
@@ -115,6 +116,10 @@ restconf_handle_init(void)
int
restconf_handle_exit(clicon_handle h)
{
+ struct restconf_handle *rh = handle(h);
+
+ if (rh->rh_fcgi_socket)
+ free(rh->rh_fcgi_socket);
clicon_handle_exit(h); /* frees h and options (and streams) */
return 0;
}
@@ -240,3 +245,36 @@ restconf_pretty_set(clicon_handle h,
rh->rh_pretty = pretty;
return 0;
}
+
+/*! Get restconf fcgi socket path
+ * @param[in] h Clicon handle
+ * @retval socketpath
+ */
+char*
+restconf_fcgi_socket_get(clicon_handle h)
+{
+ struct restconf_handle *rh = handle(h);
+
+ return rh->rh_fcgi_socket;
+}
+
+/*! Set restconf fcgi socketpath
+ * @param[in] h Clicon handle
+ * @param[in] name Data name
+ * @param[in] val Data value as null-terminated string
+ * @retval 0 OK
+ * @retval -1 Error
+ * Currently using clixon runtime data but there is risk for colliding names
+ */
+int
+restconf_fcgi_socket_set(clicon_handle h,
+ char *socketpath)
+{
+ struct restconf_handle *rh = handle(h);
+
+ if ((rh->rh_fcgi_socket = strdup(socketpath)) == NULL){
+ clicon_err(OE_RESTCONF, errno, "strdup");
+ return -1;
+ }
+ return 0;
+}
diff --git a/apps/restconf/restconf_handle.h b/apps/restconf/restconf_handle.h
index b19b7aca..f567c4ea 100644
--- a/apps/restconf/restconf_handle.h
+++ b/apps/restconf/restconf_handle.h
@@ -51,5 +51,7 @@ clixon_auth_type_t restconf_auth_type_get(clicon_handle h);
int restconf_auth_type_set(clicon_handle h, clixon_auth_type_t type);
int restconf_pretty_get(clicon_handle h);
int restconf_pretty_set(clicon_handle h, int pretty);
+char *restconf_fcgi_socket_get(clicon_handle h);
+int restconf_fcgi_socket_set(clicon_handle h, char *socketpath);
#endif /* _RESTCONF_HANDLE_H_ */
diff --git a/apps/restconf/restconf_lib.c b/apps/restconf/restconf_lib.c
index ec245721..4376a3cc 100644
--- a/apps/restconf/restconf_lib.c
+++ b/apps/restconf/restconf_lib.c
@@ -754,7 +754,15 @@ restconf_config_init(clicon_handle h,
char *bstr;
cvec *nsc = NULL;
int auth_type;
-
+ yang_stmt *yspec;
+
+ if ((yspec = clicon_dbspec_yang(h)) == NULL){
+ clicon_err(OE_FATAL, 0, "No DB_SPEC");
+ goto done;
+ }
+ /* Apply default values (removed in clear function) */
+ if (xml_default_recurse(xrestconf, 0) < 0)
+ goto done;
if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL &&
(enable = xml_body(x)) != NULL){
if (strcmp(enable, "false") == 0){
@@ -778,6 +786,11 @@ restconf_config_init(clicon_handle h,
else if (strcmp(bstr, "false") == 0)
restconf_pretty_set(h, 0);
}
+ if ((x = xpath_first(xrestconf, nsc, "fcgi-socket")) != NULL &&
+ (bstr = xml_body(x)) != NULL){
+ if (restconf_fcgi_socket_set(h, bstr) < 0)
+ goto done;
+ }
retval = 1;
done:
return retval;
diff --git a/apps/restconf/restconf_main_fcgi.c b/apps/restconf/restconf_main_fcgi.c
index e886789d..f10d4b2e 100644
--- a/apps/restconf/restconf_main_fcgi.c
+++ b/apps/restconf/restconf_main_fcgi.c
@@ -125,6 +125,90 @@ fcgi_params_set(clicon_handle h,
return retval;
}
+/*! Try to get config: inline, config-file or query backend
+ */
+static int
+restconf_main_config(clicon_handle h,
+ yang_stmt *yspec,
+ const char *inline_config)
+{
+ int retval = -1;
+ struct passwd *pw;
+ cxobj *xconfig = NULL;
+ cxobj *xrestconf = NULL;
+ uint32_t id = 0;
+ cxobj *xerr = NULL;
+ int configure_done = 0; /* First try local then backend */
+ cvec *nsc = NULL;
+ int ret;
+
+ /* 1. try inline configure option */
+ if (inline_config != NULL && strlen(inline_config)){
+ clicon_debug(1, "restconf_main_fcgi using restconf inline config");
+ if ((ret = clixon_xml_parse_string(inline_config, YB_MODULE, yspec, &xrestconf, &xerr)) < 0)
+ goto done;
+ if (ret == 0){
+ clixon_netconf_error(xerr, "Inline restconf config", NULL);
+ goto done;
+ }
+ /* Replace parent w first child */
+ if (xml_rootchild(xrestconf, 0, &xrestconf) < 0)
+ goto done;
+ }
+ else if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS") == 0){
+ /* 2. If not read from backend, try to get restconf config from local config-file */
+ xrestconf = clicon_conf_restconf(h);
+ }
+ /* 3. If no local config, or it is disabled, try to query backend of config. */
+ else {
+ /* Loop to wait for backend starting, try again if not done */
+ while (1){
+ if (clicon_hello_req(h, &id) < 0){
+ if (errno == ENOENT){
+ fprintf(stderr, "waiting");
+ sleep(1);
+ continue;
+ }
+ clicon_err(OE_UNIX, errno, "clicon_session_id_get");
+ goto done;
+ }
+ clicon_session_id_set(h, id);
+ break;
+ }
+ if ((nsc = xml_nsctx_init(NULL, CLIXON_RESTCONF_NS)) == NULL)
+ goto done;
+ if ((pw = getpwuid(getuid())) == NULL){
+ clicon_err(OE_UNIX, errno, "getpwuid");
+ goto done;
+ }
+ if (clicon_rpc_get_config(h, pw->pw_name, "running", "/restconf", nsc, &xconfig) < 0)
+ goto done;
+ if ((xerr = xpath_first(xconfig, NULL, "/rpc-error")) != NULL){
+ clixon_netconf_error(xerr, "Get backend restconf config", NULL);
+ goto done;
+ }
+ /* Extract restconf configuration */
+ xrestconf = xpath_first(xconfig, nsc, "restconf");
+ }
+ configure_done = 0;
+ if (xrestconf != NULL &&
+ (configure_done = restconf_config_init(h, xrestconf)) < 0)
+ goto done;
+ if (!configure_done){ /* Query backend of config. */
+ clicon_err(OE_DAEMON, EFAULT, "Restconf daemon config not found or disabled");
+ goto done;
+ }
+ retval = 0;
+ done:
+ if (nsc)
+ cvec_free(nsc);
+ if (inline_config != NULL && strlen(inline_config) && xrestconf)
+ xml_free(xrestconf);
+ if (xconfig)
+ xml_free(xconfig);
+ return retval;
+}
+
/* XXX Need global variable to for SIGCHLD signal handler
*/
static clicon_handle _CLICON_HANDLE = NULL;
@@ -221,20 +305,11 @@ main(int argc,
int finish = 0;
char *str;
clixon_plugin_t *cp = NULL;
- uint32_t id = 0;
cvec *nsctx_global = NULL; /* Global namespace context */
size_t cligen_buflen;
size_t cligen_bufthreshold;
int dbg = 0;
- int ret;
- cxobj *xrestconf1 = NULL; /* Inline */
- cxobj *xrestconf2 = NULL; /* Local config file */
- cxobj *xconfig3 = NULL;
- cxobj *xrestconf3 = NULL; /* Config from backend */
- int configure_done = 0; /* First try local then backend */
- cvec *nsc = NULL;
cxobj *xerr = NULL;
- struct passwd *pw;
char *wwwuser;
char *inline_config = NULL;
@@ -457,83 +532,13 @@ main(int argc,
if (clixon_plugin_start_all(h) < 0)
goto done;
- /* 1. try inline configure option */
- if (inline_config != NULL && strlen(inline_config)){
- clicon_debug(1, "restconf_main_fcgi using restconf inline config");
- if ((ret = clixon_xml_parse_string(inline_config, YB_MODULE, yspec, &xrestconf1, &xerr)) < 0)
- goto done;
- if (ret == 0){
- clixon_netconf_error(xerr, "Inline restconf config", NULL);
- goto done;
- }
- /* Replace parent w first child */
- if (xml_rootchild(xrestconf1, 0, &xrestconf1) < 0)
- goto done;
- if ((ret = restconf_config_init(h, xrestconf1)) < 0)
- goto done;
- if (ret == 1)
- configure_done = 1;
- }
- else if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS") == 0){
- /* 2. If not read from backend, try to get restconf config from local config-file */
- if ((xrestconf2 = clicon_conf_restconf(h)) != NULL){
- if ((ret = restconf_config_init(h, xrestconf2)) < 0)
- goto done;
- if (ret == 1)
- configure_done = 1;
- }
- }
- /* 3. If no local config, or it is disabled, try to query backend of config. */
- else {
- /* Loop to wait for backend starting, try again if not done */
- while (1){
- if (clicon_hello_req(h, &id) < 0){
- if (errno == ENOENT){
- fprintf(stderr, "waiting");
- sleep(1);
- continue;
- }
- clicon_err(OE_UNIX, errno, "clicon_session_id_get");
- goto done;
- }
- clicon_session_id_set(h, id);
- break;
- }
- if ((nsc = xml_nsctx_init(NULL, CLIXON_RESTCONF_NS)) == NULL)
- goto done;
- if ((pw = getpwuid(getuid())) == NULL){
- clicon_err(OE_UNIX, errno, "getpwuid");
- goto done;
- }
- if (clicon_rpc_get_config(h, pw->pw_name, "running", "/restconf", nsc, &xconfig3) < 0)
- goto done;
- if ((xerr = xpath_first(xconfig3, NULL, "/rpc-error")) != NULL){
- clixon_netconf_error(xerr, "Get backend restconf config", NULL);
- goto done;
- }
- /* Extract restconf configuration */
- if ((xrestconf3 = xpath_first(xconfig3, nsc, "restconf")) != NULL){
- if ((ret = restconf_config_init(h, xrestconf3)) < 0)
- goto done;
- if (ret == 1)
- configure_done = 1;
- }
- }
- if (!configure_done){ /* Query backend of config. */
- clicon_err(OE_DAEMON, EFAULT, "Restconf daemon config not found or disabled");
+ /* Try to get config: inline, config-file or query backend */
+ if (restconf_main_config(h, yspec, inline_config) < 0)
goto done;
- }
- /* XXX see restconf_config_init access directly */
- if ((sockpath = clicon_option_str(h, "CLICON_RESTCONF_PATH")) == NULL){
- clicon_err(OE_CFG, errno, "No CLICON_RESTCONF_PATH in clixon configure file");
+ if ((sockpath = restconf_fcgi_socket_get(h)) == NULL){
+ clicon_err(OE_CFG, 0, "No restconf fcgi-socket (have you set FEATURE fcgi in config?)");
goto done;
}
- /* XXX CLICON_RESTCONF_PATH is marked as obsolete and should use
- * fcgi-socket in clixon-restconf.yang instead */
- if ((sockpath = clicon_option_str(h, "CLICON_RESTCONF_PATH")) == NULL){
- clicon_err(OE_CFG, errno, "No CLICON_RESTCONF_PATH in clixon configure file");
- goto done;
- }
if (FCGX_Init() != 0){ /* How to cleanup memory after this? */
clicon_err(OE_CFG, errno, "FCGX_Init");
goto done;
@@ -649,12 +654,6 @@ main(int argc,
} /* while */
retval = 0;
done:
- if (xrestconf1)
- xml_free(xrestconf1);
- if (xconfig3)
- xml_free(xconfig3);
- if (nsc)
- cvec_free(nsc);
stream_child_freeall(h);
restconf_terminate(h);
return retval;
diff --git a/test/lib.sh b/test/lib.sh
index a70766cd..12d5ba50 100755
--- a/test/lib.sh
+++ b/test/lib.sh
@@ -226,8 +226,13 @@ function restconf_config()
AUTH=$1
PRETTY=$2
+ if [ ${WITH_RESTCONF} = "fcgi" ]; then
+ FEATURES="clixon-restconf:fcgi"
+ else
+ FEATURES=""
+ fi
if [ $RCPROTO = http ]; then
- echo "true$AUTH$PRETTY$DBGdefault0.0.0.080false"
+ echo "${FEATURES}true$AUTH$PRETTY$DBGdefault0.0.0.080false"
else
certdir=$dir/certs
if [ ! -f ${dir}/clixon-server-crt.pem ]; then
@@ -240,7 +245,7 @@ function restconf_config()
cacerts $cakey $cacert
servercerts $cakey $cacert $srvkey $srvcert
fi
- echo "true$AUTH$PRETTY${certdir}/clixon-server-crt.pem${certdir}/clixon-server-key.pem${certdir}/clixon-ca-crt.pem$DBGdefault0.0.0.0443true"
+ echo "${FEATURES}true$AUTH$PRETTY${certdir}/clixon-server-crt.pem${certdir}/clixon-server-key.pem${certdir}/clixon-ca-crt.pem$DBGdefault0.0.0.0443true"
fi
}
diff --git a/test/test_restconf.sh b/test/test_restconf.sh
index e13d6222..fe6b1088 100755
--- a/test/test_restconf.sh
+++ b/test/test_restconf.sh
@@ -537,7 +537,9 @@ function testrun()
}
# Go thru all combinations of IPv4/IPv6, http/https, local/backend config
-if ${HAVE_LIBEVHTP}; then
+if [ "${WITH_RESTCONF}" = "fcgi" ]; then
+ protos="http"
+elif ${HAVE_LIBEVHTP}; then
protos="http" # No plain http for http/2 only
fi
if [ "${WITH_RESTCONF}" = "native" ]; then
diff --git a/test/test_restconf_err.sh b/test/test_restconf_err.sh
index 9d0d85eb..bebd0a6b 100755
--- a/test/test_restconf_err.sh
+++ b/test/test_restconf_err.sh
@@ -23,7 +23,8 @@
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
-if ! ${HAVE_LIBEVHTP}; then
+# Does not work with evhtpnative http/2-only
+if [ "${WITH_RESTCONF}" = "native" -a ${HAVE_LIBEVHTP} = false ]; then
echo "...skipped: LIBEVHTP is false, must run with http/1 (evhtp)"
if [ "$s" = $0 ]; then exit 0; else return 0; fi
fi
diff --git a/test/test_restconf_internal.sh b/test/test_restconf_internal.sh
index 216b9e38..e7004d75 100755
--- a/test/test_restconf_internal.sh
+++ b/test/test_restconf_internal.sh
@@ -14,7 +14,8 @@
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
-if ! ${HAVE_LIBEVHTP}; then
+# Does not work with evhtpnative http/2-only
+if [ "${WITH_RESTCONF}" = "native" -a ${HAVE_LIBEVHTP} = false ]; then
echo "...skipped: LIBEVHTP is false, must run with http/1 (evhtp)"
if [ "$s" = $0 ]; then exit 0; else return 0; fi
fi
diff --git a/test/test_restconf_internal_usecases.sh b/test/test_restconf_internal_usecases.sh
index 74d61316..9631f5e1 100755
--- a/test/test_restconf_internal_usecases.sh
+++ b/test/test_restconf_internal_usecases.sh
@@ -25,7 +25,8 @@
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
-if ! ${HAVE_LIBEVHTP}; then
+# Does not work with evhtpnative http/2-only
+if [ "${WITH_RESTCONF}" = "native" -a ${HAVE_LIBEVHTP} = false ]; then
echo "...skipped: LIBEVHTP is false, must run with http/1 (evhtp)"
if [ "$s" = $0 ]; then exit 0; else return 0; fi
fi