Preparations for 6.2.0
Openssl 3.0 and autoconf 2.71
This commit is contained in:
parent
4643540391
commit
5d1c6b5759
8 changed files with 2764 additions and 2151 deletions
|
|
@ -380,143 +380,6 @@ netconf_input_packet(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
#ifndef NETCONF_INPUT_UNIFIED_EXTERN
|
||||
/*! Process incoming frame, ie a char message framed by ]]>]]>
|
||||
* Parse string to xml, check only one netconf message within a frame
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] cb Packet buffer
|
||||
* @param[out] eof Set to 1 if pending close socket
|
||||
* @retval 0 OK
|
||||
* @retval -1 Fatal error
|
||||
* @note there are errors detected here prior to whether you know what kind if message it is, and
|
||||
* these errors are returned as "rpc-error".
|
||||
* This is problematic since RFC6241 only says to return rpc-error on errors to <rpc>.
|
||||
* Not at this early stage, the incoming message can be something else such as <hello> or
|
||||
* something else.
|
||||
* In section 8.1 regarding handling of <hello> it says just to "terminate" the session which I
|
||||
* interpret as not sending anything back, just closing the session.
|
||||
* Anyway, clixon therefore does the following on error:
|
||||
* - Before we know what it is: send rpc-error
|
||||
* - Hello messages: terminate
|
||||
* - RPC messages: send rpc-error
|
||||
*/
|
||||
static int
|
||||
netconf_input_frame1(clicon_handle h,
|
||||
cbuf *cb,
|
||||
int *eof)
|
||||
{
|
||||
int retval = -1;
|
||||
char *str = NULL;
|
||||
cxobj *xtop = NULL; /* Request (in) */
|
||||
cxobj *xreq = NULL;
|
||||
cxobj *xret = NULL; /* Return (out) */
|
||||
cbuf *cbret = NULL;
|
||||
yang_stmt *yspec;
|
||||
int ret;
|
||||
netconf_framing_type framing;
|
||||
|
||||
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
|
||||
clicon_debug(CLIXON_DBG_MSG, "Recv ext: %s", cbuf_get(cb));
|
||||
framing = clicon_data_int_get(h, NETCONF_FRAMING_TYPE);
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if ((str = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
/* Special case: */
|
||||
if (strlen(str) == 0){
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_operation_failed(cbret, "rpc", "Empty XML")< 0)
|
||||
goto done;
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Parse incoming XML message */
|
||||
if ((ret = clixon_xml_parse_string(str, YB_RPC, yspec, &xtop, &xret)) < 0){
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_operation_failed(cbret, "rpc", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (ret == 0){
|
||||
/* Note: xtop can be "hello" in which case one (maybe) should drop the session and log
|
||||
* However, its not until netconf_input_packet that rpc vs hello vs other identification is
|
||||
* actually made.
|
||||
* Actually, there are no error replies to hello messages according to any RFC, so
|
||||
* rpc error reply here is non-standard, but may be useful.
|
||||
*/
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
|
||||
goto done;
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Check for empty frame (no mesaages), return empty message, not clear from RFC what to do */
|
||||
if (xml_child_nr_type(xtop, CX_ELMNT) == 0){
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Check for multi-messages in frame */
|
||||
if (xml_child_nr_type(xtop, CX_ELMNT) != 1){
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_malformed_message(cbret, "More than one message in netconf rpc frame")< 0)
|
||||
goto done;
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if ((xreq = xml_child_i_type(xtop, 0, CX_ELMNT)) == NULL){ /* Shouldnt happen */
|
||||
clicon_err(OE_XML, EFAULT, "No xml req (shouldnt happen)");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_input_packet(h, xreq, yspec, eof) < 0)
|
||||
goto done;
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (str)
|
||||
free(str);
|
||||
if (xtop)
|
||||
xml_free(xtop);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
if (cbret)
|
||||
cbuf_free(cbret);
|
||||
return retval;
|
||||
}
|
||||
#endif /* NETCONF_INPUT_UNIFIED_EXTERN */
|
||||
|
||||
/*! Get netconf message: detect end-of-msg
|
||||
* @param[in] s Socket where input arrived. read from this.
|
||||
* @param[in] arg Clixon handle.
|
||||
|
|
@ -528,7 +391,6 @@ netconf_input_frame1(clicon_handle h,
|
|||
* <a>foo ..pause.. </a>]]>]]>
|
||||
* then only "</a>" would be delivered to netconf_input_frame().
|
||||
*/
|
||||
#ifdef NETCONF_INPUT_UNIFIED_EXTERN
|
||||
static int
|
||||
netconf_input_cb(int s,
|
||||
void *arg)
|
||||
|
|
@ -659,137 +521,6 @@ netconf_input_cb(int s,
|
|||
return retval;
|
||||
}
|
||||
|
||||
#else /* NETCONF_INPUT_UNIFIED_EXTERN */
|
||||
|
||||
static int
|
||||
netconf_input_cb(int s,
|
||||
void *arg)
|
||||
{
|
||||
int retval = -1;
|
||||
unsigned char buf[BUFSIZ]; /* from stdio.h, typically 8K */
|
||||
clicon_handle h = arg;
|
||||
cbuf *cb=NULL;
|
||||
void *ptr;
|
||||
size_t cdatlen = 0;
|
||||
clicon_hash_t *cdat = clicon_data(h); /* Save cbuf between calls if not done */
|
||||
int poll;
|
||||
int i;
|
||||
int len;
|
||||
int frame_state;
|
||||
size_t frame_size;
|
||||
int ret;
|
||||
int eof = 0; /* Set to 1 if pending close socket */
|
||||
|
||||
if (clicon_option_exists(h, NETCONF_FRAME_STATE) == 0)
|
||||
frame_state = 0;
|
||||
else
|
||||
if ((frame_state = clicon_option_int(h, NETCONF_FRAME_STATE)) < 0)
|
||||
goto done;
|
||||
if (clicon_option_exists(h, NETCONF_FRAME_SIZE) == 0)
|
||||
frame_size = 0;
|
||||
else{
|
||||
if ((ret = clicon_option_int(h, NETCONF_FRAME_SIZE)) < 0)
|
||||
goto done;
|
||||
frame_size = (size_t)ret;
|
||||
}
|
||||
if ((ptr = clicon_hash_value(cdat, NETCONF_FRAME_MSG, &cdatlen)) != NULL){
|
||||
if (cdatlen != sizeof(cb)){
|
||||
clicon_err(OE_XML, errno, "size mismatch %lu %lu",
|
||||
(unsigned long)cdatlen, (unsigned long)sizeof(cb));
|
||||
goto done;
|
||||
}
|
||||
cb = *(cbuf**)ptr;
|
||||
clicon_hash_del(cdat, NETCONF_FRAME_MSG);
|
||||
}
|
||||
else{
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
while (1){
|
||||
if ((len = read(s, buf, sizeof(buf))) < 0){
|
||||
if (errno == ECONNRESET)
|
||||
len = 0; /* emulate EOF */
|
||||
else{
|
||||
clicon_log(LOG_ERR, "%s: read: %s", __FUNCTION__, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
} /* read */
|
||||
if (len == 0){ /* EOF */
|
||||
clicon_debug(1, "%s len==0, closing", __FUNCTION__);
|
||||
clixon_event_unreg_fd(s, netconf_input_cb);
|
||||
close(s);
|
||||
clixon_exit_set(1);
|
||||
goto ok;
|
||||
}
|
||||
for (i=0; i<len; i++){
|
||||
if (buf[i] == 0)
|
||||
continue; /* Skip NULL chars (eg from terminals) */
|
||||
if (clicon_data_int_get(h, NETCONF_FRAMING_TYPE) == NETCONF_SSH_CHUNKED){
|
||||
/* Track chunked framing defined in RFC6242 */
|
||||
if ((ret = netconf_input_chunked_framing(buf[i], &frame_state, &frame_size)) < 0)
|
||||
goto done;
|
||||
switch (ret){
|
||||
case 1: /* chunk-data */
|
||||
cprintf(cb, "%c", buf[i]);
|
||||
break;
|
||||
case 2: /* end-of-data */
|
||||
/* Somewhat complex error-handling:
|
||||
* Ignore packet errors, UNLESS an explicit termination request (eof)
|
||||
*/
|
||||
if (netconf_input_frame1(h, cb, &eof) < 0 &&
|
||||
!ignore_packet_errors)
|
||||
goto done;
|
||||
if (eof)
|
||||
goto done;
|
||||
cbuf_reset(cb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
cprintf(cb, "%c", buf[i]);
|
||||
if (detect_endtag("]]>]]>", buf[i], &frame_state)){
|
||||
frame_state = 0;
|
||||
/* OK, we have an xml string from a client */
|
||||
/* Remove trailer */
|
||||
*(((char*)cbuf_get(cb)) + cbuf_len(cb) - strlen("]]>]]>")) = '\0';
|
||||
if (netconf_input_frame1(h, cb, &eof) < 0 &&
|
||||
!ignore_packet_errors) // default is to ignore errors
|
||||
goto done;
|
||||
if (eof)
|
||||
goto done;
|
||||
cbuf_reset(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* poll==1 if more, poll==0 if none */
|
||||
if ((poll = clixon_event_poll(s)) < 0)
|
||||
goto done;
|
||||
if (poll == 0){
|
||||
/* No data to read, save data and continue on next round */
|
||||
if (cbuf_len(cb) != 0){
|
||||
if (clicon_hash_add(cdat, NETCONF_FRAME_MSG, &cb, sizeof(cb)) == NULL)
|
||||
goto done;
|
||||
cb = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} /* while */
|
||||
ok:
|
||||
clicon_option_int_set(h, NETCONF_FRAME_STATE, frame_state);
|
||||
clicon_option_int_set(h, NETCONF_FRAME_SIZE, frame_size);
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
return retval;
|
||||
}
|
||||
#endif /* NETCONF_INPUT_UNIFIED_EXTERN */
|
||||
|
||||
/*! Send netconf hello message
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] s File descriptor to write on (eg 1 - stdout)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue