/* * Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren This file is part of CLICON. CLICON is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. CLICON is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with CLICON; see the file COPYING. If not, see . * * netconf lib *****************************************************************************/ #ifdef HAVE_CONFIG_H #include "clicon_config.h" /* generated by config & autoconf */ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* cligen */ #include /* clicon */ #include #include "netconf_rpc.h" #include "netconf_lib.h" /* * Exported variables */ enum transport_type transport = NETCONF_SSH; int cc_closed = 0; static int cc_ok = 0; void netconf_ok_set(int ok) { cc_ok = ok; } int netconf_ok_get(void) { return cc_ok; } int add_preamble(cbuf *xf) { if (transport == NETCONF_SOAP) cprintf(xf, "\n\n" ""); return 0; } /* * add_postamble * add netconf xml postamble of message. That is, xml after the body of the message. * for soap this is the envelope stuff, for ssh this is ]]>]]> */ int add_postamble(cbuf *xf) { switch (transport){ case NETCONF_SSH: cprintf(xf, "]]>]]>"); /* Add RFC4742 end-of-message marker */ break; case NETCONF_SOAP: cprintf(xf, "\n" ""); break; } return 0; } /* * add_error_preamble * compared to regular messages (see add_preamble), error message differ in some * protocols (eg soap) by adding a longer and deeper header. */ int add_error_preamble(cbuf *xf, char *reason) { switch (transport){ case NETCONF_SOAP: cprintf(xf, "" "" "" "" "env:Receiver" "" "" "%s" "" "", reason); break; default: if (add_preamble(xf) < 0) return -1; break; } return 0; } /* * add_error_postamble * compared to regular messages (see add_postamble), error message differ in some * protocols (eg soap) by adding a longer and deeper header. */ int add_error_postamble(cbuf *xf) { switch (transport){ case NETCONF_SOAP: cprintf(xf, "" ""); default: /* fall through */ if (add_postamble(xf) < 0) return -1; break; } return 0; } /*! Look for a text pattern in an input string, one char at a time * @param[in] tag What to look for * @param[in] ch New input character * @param[in,out] state A state integer holding how far we have parsed. * @retval 0 No, we havent detected end tag * @retval 1 Yes, we have detected end tag! * XXX: move to clicon_xml? */ int detect_endtag(char *tag, char ch, int *state) { int retval = 0; if (tag[*state] == ch){ (*state)++; if (*state == strlen(tag)){ *state = 0; retval = 1; } } else *state = 0; return retval; } /* * target_locked * return 1 if locked, 0 if not. * return clientid if locked. */ int target_locked(enum target_type target, int *client) { return 0; } /* * unlock_target */ int unlock_target(enum target_type target) { return 0; } int lock_target(enum target_type target) { return 0; } /*! Get "target" attribute, return actual database given candidate or running * Caller must do error handling * @retval dbname Actual database file name */ char * netconf_get_target(clicon_handle h, cxobj *xn, char *path) { cxobj *x; char *target = NULL; char *running_db; char *candidate_db; if ((running_db = clicon_running_db(h)) == NULL) goto done; if ((candidate_db = clicon_candidate_db(h)) == NULL) goto done; if ((x = xpath_first(xn, path)) != NULL){ if (xpath_first(x, "candidate") != NULL) target = candidate_db; else if (xpath_first(x, "running") != NULL) target = running_db; } done: return target; } /*! Send netconf message from cbuf on socket * @param[in] s * @param[in] cb Cligen buffer that contains the XML message * @param[in] msg Only for debug */ int netconf_output(int s, cbuf *xf, char *msg) { char *buf = cbuf_get(xf); int len = cbuf_len(xf); int retval = -1; clicon_debug(1, "SEND %s", msg); if (debug > 1){ /* XXX: below only works to stderr, clicon_debug may log to syslog */ cxobj *xt = NULL; if (clicon_xml_parse_string(&buf, &xt) == 0){ clicon_xml2file(stderr, xml_child_i(xt, 0), 0, 0); fprintf(stderr, "\n"); xml_free(xt); } } if (write(s, buf, len) < 0){ if (errno == EPIPE) ; else clicon_log(LOG_ERR, "%s: write: %s", __FUNCTION__, strerror(errno)); goto done; } retval = 0; done: return retval; }