From 3443dbd33ff1094700e4c812a0d9ba7bfd77521d Mon Sep 17 00:00:00 2001 From: Olof Hagsand Date: Mon, 26 Sep 2016 21:44:17 +0200 Subject: [PATCH] restconf plugins and figthing with xml->json translation --- apps/cli/cli_common.c | 2 +- apps/cli/cli_show.c | 2 +- apps/restconf/README | 2 +- apps/restconf/restconf_lib.c | 48 ++++++++++++++++++++++++++------ apps/restconf/restconf_lib.h | 2 +- apps/restconf/restconf_main.c | 41 +++++++++++++++------------ lib/clixon/clixon_json.h | 5 ++-- lib/src/clixon_json.c | 52 +++++++++++++++++++++++++---------- lib/src/clixon_xml_db.c | 14 ++++++---- 9 files changed, 117 insertions(+), 51 deletions(-) diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c index 7ab70b54..1b7888f8 100644 --- a/apps/cli/cli_common.c +++ b/apps/cli/cli_common.c @@ -835,7 +835,7 @@ cli_notification_cb(int s, void *arg) if (clicon_xml_parse_string(&eventstr, &xt) < 0) goto done; if ((xn = xml_child_i(xt, 0)) != NULL){ - if (xml2json(stdout, xn, 0, 1) < 0) + if (xml2json(stdout, xn, 0) < 0) goto done; } } diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 60e60044..62323f0f 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -443,7 +443,7 @@ show_conf_as_json(clicon_handle h, if (show_conf_as(h, cvv, arg, &xt) < 0) goto done; - xml2json(stdout, xt, 1, 0); + xml2json(stdout, xt, 1); retval = 0; done: if (xt) diff --git a/apps/restconf/README b/apps/restconf/README index b850b53e..5ecfc1ef 100644 --- a/apps/restconf/README +++ b/apps/restconf/README @@ -56,7 +56,7 @@ olof@vandal> curl -G http://127.0.0.1/restconf/data/interfaces/interface/name=et Debugging --------- -Start the fastcgi programs with debug flag: +Start the restconf programs with debug flag: sudo su -c "/www-data/clixon_restconf -D" -s /bin/sh www-data Look at syslog: diff --git a/apps/restconf/restconf_lib.c b/apps/restconf/restconf_lib.c index aaa2e276..53b20105 100644 --- a/apps/restconf/restconf_lib.c +++ b/apps/restconf/restconf_lib.c @@ -231,8 +231,11 @@ readdata(FCGX_Request *r) return cb; } +typedef int (credentials_t)(clicon_handle h, FCGX_Request *r); + static int nplugins = 0; static plghndl_t *plugins = NULL; +static credentials_t *p_credentials = NULL; /* Credentials callback */ /*! Load a dynamic plugin object and call it's init-function * Note 'file' may be destructively modified @@ -247,22 +250,29 @@ plugin_load (clicon_handle h, void *handle = NULL; plginit_t *initfn; + clicon_debug(1, "%s", __FUNCTION__); dlerror(); /* Clear any existing error */ if ((handle = dlopen (file, dlflags)) == NULL) { error = (char*)dlerror(); clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error"); - goto quit; + goto done; } /* call plugin_init() if defined */ - if ((initfn = dlsym(handle, PLUGIN_INIT)) != NULL) { - if (initfn(h) != 0) { - clicon_err(OE_PLUGIN, errno, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file); - goto quit; - } + if ((initfn = dlsym(handle, PLUGIN_INIT)) == NULL){ + clicon_err(OE_PLUGIN, errno, "Failed to find plugin_init when loading restconf plugin %s", file); + goto err; } -quit: - + if (initfn(h) != 0) { + clicon_err(OE_PLUGIN, errno, "Failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file); + goto err; + } + p_credentials = dlsym(handle, "restconf_credentials"); + done: return handle; + err: + if (handle) + dlclose(handle); + return NULL; } @@ -371,3 +381,25 @@ restconf_plugin_start(clicon_handle h, return 0; } +int +plugin_credentials(clicon_handle h, + FCGX_Request *r, + int *auth) +{ + int retval = -1; + + clicon_debug(1, "%s", __FUNCTION__); + /* If no authentication callback then allow anything. Is this OK? */ + if (p_credentials == 0){ + *auth = 1; + retval = 0; + goto done; + } + if (p_credentials(h, r) < 0) + *auth = 0; + else + *auth = 1; + retval = 0; + done: + return retval; +} diff --git a/apps/restconf/restconf_lib.h b/apps/restconf/restconf_lib.h index d6b5c5f8..548e30e1 100644 --- a/apps/restconf/restconf_lib.h +++ b/apps/restconf/restconf_lib.h @@ -34,6 +34,6 @@ cbuf *readdata(FCGX_Request *r); int restconf_plugin_load(clicon_handle h); int restconf_plugin_start(clicon_handle h, int argc, char **argv); int restconf_plugin_unload(clicon_handle h); - +int plugin_credentials(clicon_handle h, FCGX_Request *r, int *auth); #endif /* _RESTCONF_LIB_H_ */ diff --git a/apps/restconf/restconf_main.c b/apps/restconf/restconf_main.c index 2820a5f0..4bac2d87 100644 --- a/apps/restconf/restconf_main.c +++ b/apps/restconf/restconf_main.c @@ -139,8 +139,8 @@ api_data_get(clicon_handle h, cvec *cvk = NULL; /* vector of index keys */ cg_var *cvi; - yspec = clicon_dbspec_yang(h); clicon_debug(1, "%s", __FUNCTION__); + yspec = clicon_dbspec_yang(h); if ((path = cbuf_new()) == NULL) goto done; if ((path1 = cbuf_new()) == NULL) /* without [] qualifiers */ @@ -179,6 +179,7 @@ api_data_get(clicon_handle h, if ((ykey = yang_find((yang_node*)y, Y_KEY, NULL)) == NULL){ clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key", __FUNCTION__, y->ys_argument); + notfound(r); goto done; } clicon_debug(1, "ykey:%s", ykey->ys_argument); @@ -202,21 +203,25 @@ api_data_get(clicon_handle h, cprintf(path1, "/%s", name); } } - if (xmldb_get(h, "running", cbuf_get(path), 0, &xt, &vec, &veclen) < 0) + clicon_debug(1, "%s path:%s", __FUNCTION__, cbuf_get(path)); + if (xmldb_get(h, "running", cbuf_get(path), 1, &xt, &vec, &veclen) < 0) goto done; + + if ((cbx = cbuf_new()) == NULL) + goto done; + if (veclen==0){ + notfound(r); + goto done; + } FCGX_SetExitStatus(200, r->out); /* OK */ FCGX_FPrintF(r->out, "Content-Type: application/yang.data+json\r\n"); FCGX_FPrintF(r->out, "\r\n"); - if ((cbx = cbuf_new()) == NULL) + if (xml2json_cbuf_vec(cbx, vec, veclen, 0) < 0) goto done; - if (xml2json_cbuf(cbx, xt, 1, 0) < 0) - goto done; - FCGX_FPrintF(r->out, "%s", cbuf_get(cbx)); - FCGX_FPrintF(r->out, "hej\r\n\r\n"); + FCGX_FPrintF(r->out, "[%s]", cbuf_get(cbx)); + FCGX_FPrintF(r->out, "\r\n\r\n"); retval = 0; done: - if (vec) - free(vec); if (cbx) cbuf_free(cbx); if (xt) @@ -248,7 +253,6 @@ api_data_delete(clicon_handle h, clicon_debug(1, "%s api_path:%s", __FUNCTION__, api_path); for (i=0; ienvp); @@ -428,7 +428,14 @@ request_process(clicon_handle h, method = pvec[2]; retval = 0; test(r, 1); - /* XXX Credentials */ + /* If present, check credentials */ + if (plugin_credentials(h, r, &auth) < 0) + goto done; + clicon_debug(1, "%s credentials ok 1", __FUNCTION__); + if (auth == 0) + goto done; + clicon_debug(1, "%s credentials ok 2", __FUNCTION__); + if (strcmp(method, "data") == 0) /* restconf, skip /api/data */ retval = api_data(h, r, path, pcvec, 2, qvec, data); else if (strcmp(method, "test") == 0) @@ -436,6 +443,7 @@ request_process(clicon_handle h, else retval = notfound(r); done: + clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); if (dvec) cvec_free(dvec); if (qvec) @@ -445,7 +453,6 @@ request_process(clicon_handle h, if (cb) cbuf_free(cb); unchunk_group(__FUNCTION__); - clicon_debug(1, "%s end", __FUNCTION__); return retval; } diff --git a/lib/clixon/clixon_json.h b/lib/clixon/clixon_json.h index 9bf443d4..c168d48b 100644 --- a/lib/clixon/clixon_json.h +++ b/lib/clixon/clixon_json.h @@ -27,7 +27,8 @@ * Prototypes */ int json_parse_str(char *str, cxobj **xt); -int xml2json_cbuf(cbuf *cb, cxobj *x, int pretty, int top); -int xml2json(FILE *f, cxobj *x, int pretty, int top); +int xml2json_cbuf(cbuf *cb, cxobj *x, int pretty); +int xml2json_cbuf_vec(cbuf *cb, cxobj **vec, size_t veclen, int pretty); +int xml2json(FILE *f, cxobj *x, int pretty); #endif /* _CLIXON_JSON_H */ diff --git a/lib/src/clixon_json.c b/lib/src/clixon_json.c index 905cda87..414b7eb1 100644 --- a/lib/src/clixon_json.c +++ b/lib/src/clixon_json.c @@ -244,7 +244,7 @@ xml2json1_cbuf(cbuf *cb, if (xml2json1_cbuf(cb, xc, level+1, pretty) < 0) goto done; if (i1){ fprintf(stderr, "%s %s\n", __FUNCTION__, xk); clicon_xml2file(stderr, xt, 0, 1); } @@ -811,10 +812,9 @@ xmldb_get_tree(char *dbname, goto done; if ((xt = xml_new("clicon", NULL)) == NULL) goto done; - if (debug) /* debug */ - for (i = 0; i < npairs; i++) - fprintf(stderr, "%s %s\n", pairs[i].dp_key, pairs[i].dp_val?pairs[i].dp_val:""); - + for (i = 0; i < npairs; i++) + clicon_debug(2, "%s %s", pairs[i].dp_key, pairs[i].dp_val?pairs[i].dp_val:""); + // clicon_debug(1, "%s npairs:%d", __FUNCTION__, npairs); for (i = 0; i < npairs; i++) { if (get(dbname, yspec, @@ -953,6 +953,7 @@ xmldb_get_local(clicon_handle h, yang_spec *yspec; char *dbname = NULL; + clicon_debug(1, "%s", __FUNCTION__); if (db2file(h, db, &dbname) < 0) goto done; if (dbname==NULL){ @@ -1019,6 +1020,7 @@ xmldb_get(clicon_handle h, { int retval = -1; + clicon_debug(1, "%s", __FUNCTION__); if (clicon_xmldb_rpc(h)) retval = xmldb_get_rpc(h, db, xpath, vector, xtop, xvec, xlen); else @@ -1422,7 +1424,7 @@ xmldb_put_tree_local(clicon_handle h, } retval = 0; done: - clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); + // clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); if (filename) free(filename); if (ckey)