internal netconf hello mechanism to obtain session-id
This commit is contained in:
parent
59825214f3
commit
44138c0071
14 changed files with 250 additions and 264 deletions
|
|
@ -158,7 +158,7 @@ backend_client_rm(clicon_handle h,
|
|||
* @param[in] yspec Yang spec
|
||||
* @param[in] xpath Xpath selection, not used but may be to filter early
|
||||
* @param[out] xrs XML restconf-state node
|
||||
* @see netconf_create_hello
|
||||
* @see netconf_hello_server
|
||||
* @see rfc8040 Sections 9.1
|
||||
*/
|
||||
static int
|
||||
|
|
@ -1300,6 +1300,29 @@ verify_nacm_user(enum nacm_credentials_t mode,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
*/
|
||||
static int
|
||||
from_client_hello(clicon_handle h,
|
||||
cxobj *x,
|
||||
struct client_entry *ce,
|
||||
cbuf *cbret)
|
||||
|
||||
{
|
||||
int retval = -1;
|
||||
uint32_t id;
|
||||
|
||||
id = clicon_session_id_get(h);
|
||||
id++;
|
||||
clicon_session_id_set(h, id);
|
||||
cprintf(cbret, "<hello><session-id>%lu</session-id></hello>", id);
|
||||
retval = 0;
|
||||
// done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! An internal clicon message has arrived from a client. Receive and dispatch.
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] s Socket where message arrived. read from this.
|
||||
|
|
@ -1344,12 +1367,20 @@ from_client_msg(clicon_handle h,
|
|||
goto done;
|
||||
goto reply;
|
||||
}
|
||||
ce->ce_id = id;
|
||||
|
||||
if ((x = xpath_first_nsc(xt, NULL, "/rpc")) == NULL){
|
||||
if (netconf_malformed_message(cbret, "rpc keyword expected")< 0)
|
||||
goto done;
|
||||
goto reply;
|
||||
if ((x = xpath_first_nsc(xt, NULL, "/hello")) != NULL){
|
||||
if ((ret = from_client_hello(h, x, ce, cbret)) <0)
|
||||
goto done;
|
||||
goto reply;
|
||||
}
|
||||
else{
|
||||
if (netconf_malformed_message(cbret, "rpc keyword expected")< 0)
|
||||
goto done;
|
||||
goto reply;
|
||||
}
|
||||
}
|
||||
ce->ce_id = id;
|
||||
/* Populate incoming XML tree with yang -
|
||||
* should really have been dealt with by decode above
|
||||
* maybe not necessary since it should be */
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ main(int argc, char **argv)
|
|||
char *str;
|
||||
int tabmode;
|
||||
char *dir;
|
||||
uint32_t id = 0;
|
||||
|
||||
/* Defaults */
|
||||
once = 0;
|
||||
|
|
@ -595,14 +596,15 @@ main(int argc, char **argv)
|
|||
if (result < 0)
|
||||
goto done;
|
||||
}
|
||||
#if 1
|
||||
/* XXX get session id from backend hello */
|
||||
clicon_session_id_set(h, getpid());
|
||||
#endif
|
||||
|
||||
/* Go into event-loop unless -1 command-line */
|
||||
if (!once)
|
||||
if (!once){
|
||||
/* send hello request from backend hello */
|
||||
if (clicon_hello_req(h, &id) < 0)
|
||||
goto done;
|
||||
clicon_session_id_set(h, id);
|
||||
retval = cli_interactive(h);
|
||||
}
|
||||
else
|
||||
retval = 0;
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ APPL = clixon_netconf
|
|||
|
||||
# Not accessible from plugin
|
||||
APPSRC = netconf_main.c
|
||||
APPSRC += netconf_hello.c
|
||||
APPSRC += netconf_rpc.c
|
||||
APPSRC += netconf_filter.c
|
||||
APPOBJ = $(APPSRC:.c=.o)
|
||||
|
|
|
|||
|
|
@ -1,188 +0,0 @@
|
|||
/*
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the "GPL"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
*
|
||||
* Code for handling netconf hello messages
|
||||
*****************************************************************************/
|
||||
/*
|
||||
Capabilities are advertised in messages sent by each peer during
|
||||
session establishment. When the NETCONF session is opened, each peer
|
||||
(both client and server) MUST send a <hello> element containing a
|
||||
list of that peer's capabilities. Each peer MUST send at least the
|
||||
base NETCONF capability, "urn:ietf:params:netconf:base:1.0".
|
||||
<hello>
|
||||
<capabilities>
|
||||
<capability>URI</capability>
|
||||
</capabilities>
|
||||
|
||||
</hello>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/param.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clicon */
|
||||
#include <clixon/clixon.h>
|
||||
|
||||
#include "netconf_lib.h"
|
||||
#include "netconf_hello.h"
|
||||
|
||||
static int
|
||||
netconf_hello(cxobj *xn)
|
||||
{
|
||||
#ifdef nyi
|
||||
cxobj *x;
|
||||
|
||||
x = NULL;
|
||||
|
||||
while ((x = xpath_each(xn, "//capability", x)) != NULL) {
|
||||
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
netconf_hello_dispatch(cxobj *xn)
|
||||
{
|
||||
cxobj *xp;
|
||||
int retval = -1;
|
||||
|
||||
if ((xp = xpath_first(xn, "//hello")) != NULL)
|
||||
retval = netconf_hello(xp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Create Netconf hello. Single cap and defer individual to querying modules
|
||||
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] cb Msg buffer
|
||||
* @param[in] session_id Id of client session
|
||||
* Lots of dependencies here. regarding the hello protocol.
|
||||
* RFC6241 NETCONF Protocol says: (8.1)
|
||||
* MUST send a <hello> element containing a list of that peer's capabilities
|
||||
* MUST send at least the base NETCONF capability, urn:ietf:params:netconf:base:1.1
|
||||
* MAY include capabilities for previous NETCONF versions
|
||||
* A server MUST include a <session-id>
|
||||
* A client MUST NOT include a <session-id>
|
||||
* A server receiving <session-id> MUST terminate the NETCONF session.
|
||||
* A client not receiving <session-id> MUST terminate w/o sending<close-session>
|
||||
* the example shows urn:ietf:params:netconf:capability:startup:1.0
|
||||
|
||||
* RFC5277 NETCONF Event Notifications
|
||||
* urn:ietf:params:netconf:capability:notification:1.0 is advertised during the capability exchange
|
||||
*
|
||||
* RFC6022 YANG Module for NETCONF Monitoring
|
||||
* MUST advertise the capability URI "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"
|
||||
* RFC7895 Yang module library defines how to announce module features (not hell capabilities)
|
||||
* RFC7950 YANG 1.1 says (5.6.4);
|
||||
* MUST announce the modules it implements by implementing the YANG module
|
||||
* "ietf-yang-library" (RFC7895) and listing all implemented modules in the
|
||||
* "/modules-state/module" list.
|
||||
* MUST advertise urn:ietf:params:netconf:capability:yang-library:1.0?
|
||||
* revision=<date>&module-set-id=<id> in the <hello> message.
|
||||
*
|
||||
* Question: should the NETCONF in RFC6241 sections 8.2-8.9 be announced both
|
||||
* as features and as capabilities in the <hello> message according to RFC6241?
|
||||
* urn:ietf:params:netconf:capability:candidate:1.0 (8.3)
|
||||
* urn:ietf:params:netconf:capability:validate:1.1 (8.6)
|
||||
* urn:ietf:params:netconf:capability:startup:1.0 (8.7)
|
||||
* urn:ietf:params:netconf:capability:xpath:1.0 (8.9)
|
||||
* urn:ietf:params:netconf:capability:notification:1.0 (RFC5277)
|
||||
*
|
||||
* @note the hello message is created bythe netconf application, not the
|
||||
* backend, and backend may implement more modules - please consider if using
|
||||
* library routines for detecting capabilities here. In contrast, yang module
|
||||
* list (RFC7895) is processed by the backend.
|
||||
* @note encode bodies, see xml_chardata_encode()
|
||||
* @see yang_modules_state_get
|
||||
* @see netconf_module_load
|
||||
*/
|
||||
int
|
||||
netconf_create_hello(clicon_handle h,
|
||||
cbuf *cb,
|
||||
int session_id)
|
||||
{
|
||||
int retval = -1;
|
||||
char *module_set_id;
|
||||
char *ietf_yang_library_revision;
|
||||
char *encstr = NULL;
|
||||
|
||||
module_set_id = clicon_option_str(h, "CLICON_MODULE_SET_ID");
|
||||
if ((ietf_yang_library_revision = yang_modules_revision(h)) == NULL)
|
||||
goto done;
|
||||
add_preamble(cb);
|
||||
cprintf(cb, "<hello xmlns=\"%s\">", NETCONF_BASE_NAMESPACE);
|
||||
cprintf(cb, "<capabilities>");
|
||||
cprintf(cb, "<capability>urn:ietf:params:netconf:base:1.0</capability>");
|
||||
if (xml_chardata_encode(&encstr, "urn:ietf:params:netconf:capability:yang-library:1.0?revision=%s&module-set-id=%s",
|
||||
ietf_yang_library_revision,
|
||||
module_set_id) < 0)
|
||||
goto done;
|
||||
cprintf(cb, "<capability>%s</capability>", encstr);
|
||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>");
|
||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:validate:1.1</capability>");
|
||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:startup:1.0</capability>");
|
||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:xpath:1.0</capability>");
|
||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:notification:1.0</capability>");
|
||||
cprintf(cb, "</capabilities>");
|
||||
cprintf(cb, "<session-id>%lu</session-id>", (long unsigned int)session_id);
|
||||
cprintf(cb, "</hello>");
|
||||
add_postamble(cb);
|
||||
retval = 0;
|
||||
done:
|
||||
if (encstr)
|
||||
free(encstr);
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the "GPL"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
*
|
||||
* Code for handling netconf hello messages
|
||||
*****************************************************************************/
|
||||
#ifndef _NETCONF_HELLO_H_
|
||||
#define _NETCONF_HELLO_H_
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int netconf_create_hello(clicon_handle h, cbuf *cb, int session_id);
|
||||
|
||||
int netconf_hello_dispatch(cxobj *xn);
|
||||
|
||||
#endif /* _NETCONF_HELLO_H_ */
|
||||
|
|
@ -67,7 +67,6 @@
|
|||
|
||||
#include "clixon_netconf.h"
|
||||
#include "netconf_lib.h"
|
||||
#include "netconf_hello.h"
|
||||
#include "netconf_rpc.h"
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
|
|
@ -78,6 +77,33 @@
|
|||
/*! Ignore errors on packet errors: continue */
|
||||
static int ignore_packet_errors = 1;
|
||||
|
||||
static int
|
||||
netconf_hello(cxobj *xn)
|
||||
{
|
||||
#ifdef nyi
|
||||
cxobj *x;
|
||||
|
||||
x = NULL;
|
||||
|
||||
while ((x = xpath_each(xn, "//capability", x)) != NULL) {
|
||||
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
netconf_hello_dispatch(cxobj *xn)
|
||||
{
|
||||
cxobj *xp;
|
||||
int retval = -1;
|
||||
|
||||
if ((xp = xpath_first(xn, "//hello")) != NULL)
|
||||
retval = netconf_hello(xp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Process incoming packet
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] cb Packet buffer
|
||||
|
|
@ -268,7 +294,8 @@ netconf_input_cb(int s,
|
|||
*/
|
||||
static int
|
||||
send_hello(clicon_handle h,
|
||||
int s)
|
||||
int s,
|
||||
uint32_t id)
|
||||
{
|
||||
int retval = -1;
|
||||
cbuf *cb;
|
||||
|
|
@ -277,7 +304,7 @@ send_hello(clicon_handle h,
|
|||
clicon_log(LOG_ERR, "%s: cbuf_new", __FUNCTION__);
|
||||
goto done;
|
||||
}
|
||||
if (netconf_create_hello(h, cb, getpid()) < 0)
|
||||
if (netconf_hello_server(h, cb, id) < 0)
|
||||
goto done;
|
||||
if (netconf_output(s, cb, "hello") < 0)
|
||||
goto done;
|
||||
|
|
@ -334,16 +361,16 @@ usage(clicon_handle h,
|
|||
"\t-h\t\tHelp\n"
|
||||
"\t-D <level>\tDebug level\n"
|
||||
"\t-f <file>\tConfiguration file (mandatory)\n"
|
||||
"\t-l (e|o|s|f<file>) \tLog on std(e)rr, std(o)ut, (s)yslog, (f)ile (syslog is default)\n"
|
||||
"\t-l (e|o|s|f<file>) Log on std(e)rr, std(o)ut, (s)yslog(default), (f)ile\n"
|
||||
"\t-q\t\tQuiet: dont send hello prompt\n"
|
||||
"\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
|
||||
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
||||
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)\n"
|
||||
"\t-d <dir>\tSpecify netconf plugin directory dir (default: %s)\n"
|
||||
"\t-p <dir>\tYang directory path (see CLICON_YANG_DIR)\n"
|
||||
"\t-y <file>\tLoad yang spec file (override yang main module)\n"
|
||||
"\t-U <user>\tOver-ride unix user with a pseudo user for NACM.\n"
|
||||
"\t-t <sec>\tTimeout in seconds. Quit after this time.\n"
|
||||
"\t-e \tDont ignore errors on packet input.\n"
|
||||
"\t-e \t\tDont ignore errors on packet input.\n"
|
||||
"\t-o \"<option>=<value>\"\tGive configuration option overriding config file (see clixon-config.yang)\n",
|
||||
argv0,
|
||||
clicon_netconf_dir(h)
|
||||
|
|
@ -367,6 +394,7 @@ main(int argc,
|
|||
yang_stmt *yspec = NULL;
|
||||
yang_stmt *yspecfg = NULL; /* For config XXX clixon bug */
|
||||
char *str;
|
||||
uint32_t id;
|
||||
|
||||
/* Create handle */
|
||||
if ((h = clicon_handle_init()) == NULL)
|
||||
|
|
@ -534,8 +562,13 @@ main(int argc,
|
|||
clicon_session_id_set(h, getpid());
|
||||
#endif
|
||||
|
||||
/* send hello request from backend hello */
|
||||
if (clicon_hello_req(h, &id) < 0)
|
||||
goto done;
|
||||
clicon_session_id_set(h, id);
|
||||
|
||||
if (!quiet)
|
||||
send_hello(h, 1);
|
||||
send_hello(h, 1, id);
|
||||
if (event_reg_fd(0, netconf_input_cb, h, "netconf socket") < 0)
|
||||
goto done;
|
||||
if (debug)
|
||||
|
|
|
|||
|
|
@ -555,9 +555,9 @@ usage(clicon_handle h,
|
|||
"\t-p <dir>\tYang directory path (see CLICON_YANG_DIR)\n"
|
||||
"\t-d <dir>\tSpecify restconf plugin directory dir (default: %s)\n"
|
||||
"\t-y <file>\tLoad yang spec file (override yang main module)\n"
|
||||
"\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
|
||||
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
||||
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)\n"
|
||||
"\t-o \"<option>=<value>\"\tGive configuration option overriding config file (see clixon-config.yang)\n",
|
||||
"\t-o \"<option>=<value>\" Give configuration option overriding config file (see clixon-config.yang)\n",
|
||||
argv0,
|
||||
clicon_restconf_dir(h)
|
||||
);
|
||||
|
|
@ -587,6 +587,7 @@ main(int argc,
|
|||
int finish;
|
||||
char *str;
|
||||
clixon_plugin *cp = NULL;
|
||||
uint32_t id = 0;
|
||||
|
||||
/* In the startup, logs to stderr & debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||
|
|
@ -780,10 +781,11 @@ main(int argc,
|
|||
clicon_err(OE_CFG, errno, "FCGX_OpenSocket");
|
||||
goto done;
|
||||
}
|
||||
#if 1
|
||||
/* XXX get session id from backend hello */
|
||||
clicon_session_id_set(h, getpid());
|
||||
#endif
|
||||
/* send hello request from backend hello */
|
||||
if (clicon_hello_req(h, &id) < 0)
|
||||
goto done;
|
||||
clicon_session_id_set(h, id);
|
||||
|
||||
if (clicon_socket_set(h, sock) < 0)
|
||||
goto done;
|
||||
/* umask settings may interfer: we want group to write: this is 774 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue