1 /* 2 * 3 ***** BEGIN LICENSE BLOCK ***** 4 5 Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren 6 Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate) 7 8 This file is part of CLIXON. 9 10 Licensed under the Apache License, Version 2.0 (the "License"); 11 you may not use this file except in compliance with the License. 12 You may obtain a copy of the License at 13 14 http://www.apache.org/licenses/LICENSE-2.0 15 16 Unless required by applicable law or agreed to in writing, software 17 distributed under the License is distributed on an "AS IS" BASIS, 18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 See the License for the specific language governing permissions and 20 limitations under the License. 21 22 Alternatively, the contents of this file may be used under the terms of 23 the GNU General Public License Version 3 or later (the "GPL"), 24 in which case the provisions of the GPL are applicable instead 25 of those above. If you wish to allow use of your version of this file only 26 under the terms of the GPL, and not to allow others to 27 use your version of this file under the terms of Apache License version 2, 28 indicate your decision by deleting the provisions above and replace them with 29 the notice and other provisions required by the GPL. If you do not delete 30 the provisions above, a recipient may use your version of this file under 31 the terms of any one of the Apache License version 2 or the GPL. 32 33 ***** END LICENSE BLOCK ***** 34 */ 35 /* 36 * Internal prototypes, not accessed by plugin client code 37 */ 38 39 #ifndef _CLIXON_PLUGIN_H_ 40 #define _CLIXON_PLUGIN_H_ 41 42 /* 43 * Constants 44 */ 45 /* Hardcoded plugin symbol. Must exist in all plugins to kickstart 46 * @see clixon_plugin_init 47 */ 48 #define CLIXON_PLUGIN_INIT "clixon_plugin_init" 49 50 /* 51 * Types 52 */ 53 54 /*! Registered RPC callback function 55 * @param[in] h Clicon handle 56 * @param[in] xn Request: <rpc><xn></rpc> 57 * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. 58 * @param[in] arg Domain specific arg, ec client-entry or FCGX_Request 59 * @param[in] regarg User argument given at rpc_callback_register() 60 * @retval 0 OK 61 * @retval -1 Error 62 */ 63 typedef int (*clicon_rpc_cb)( 64 clicon_handle h, 65 cxobj *xn, 66 cbuf *cbret, 67 void *arg, 68 void *regarg 69 ); 70 71 /*! Registered Upgrade callback function 72 * @param[in] h Clicon handle 73 * @param[in] xn XML tree to be updated 74 * @param[in] ns Namespace of module 75 * @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE 76 * @param[in] from From revision on the form YYYYMMDD (if DEL or CHANGE) 77 * @param[in] to To revision on the form YYYYMMDD (if ADD or CHANGE) 78 * @param[in] arg User argument given at rpc_callback_register() 79 * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. (if retval = 0) 80 * @retval 1 OK 81 * @retval 0 Invalid 82 * @retval -1 Error 83 */ 84 typedef int (*clicon_upgrade_cb)( 85 clicon_handle h, 86 cxobj *xn, 87 char *ns, 88 uint16_t op, 89 uint32_t from, 90 uint32_t to, 91 void *arg, 92 cbuf *cbret 93 ); 94 95 /* 96 * Prototypes 97 */ 98 /* Common plugin function names, function types and signatures. 99 * This plugin code is exytended by backend, cli, netconf, restconf plugins 100 * Cli see cli_plugin.c 101 * Backend see config_plugin.c 102 */ 103 104 /* Called when application is "started", (almost) all initialization is complete 105 * Backend: daemon is in the background. If daemon privileges are dropped 106 * this callback is called *before* privileges are dropped. 107 */ 108 typedef int (plgstart_t)(clicon_handle); /* Plugin start */ 109 110 /* Called just after a server has "daemonized", ie put in background. 111 * Backend: If daemon privileges are dropped this callback is called *before* privileges are dropped. 112 * If daemon is started in foreground (-F) it is still called. 113 */ 114 typedef int (plgdaemon_t)(clicon_handle); /* Plugin daemonized */ 115 116 /* Called just before plugin unloaded. 117 */ 118 typedef int (plgexit_t)(clicon_handle); /* Plugin exit */ 119 120 /* For yang extension handling. 121 * Called at parsing of yang module containing a statement of an extension. 122 * A plugin may identify the extension by its name, and perform actions 123 * on the yang statement, such as transforming the yang. 124 * A callback is made for every statement, which means that several calls per 125 * extension can be made. 126 * @param[in] h Clixon handle 127 * @param[in] yext Yang node of extension 128 * @param[in] ys Yang node of (unknown) statement belonging to extension 129 * @retval 0 OK, all callbacks executed OK 130 * @retval -1 Error in one callback 131 */ 132 typedef int (plgextension_t)(clicon_handle h, yang_stmt *yext, yang_stmt *ys); 133 134 /*! Called by restconf on each incoming request to check credentials and return username 135 */ 136 137 /* Plugin authorization. Set username option (or not) 138 * @param[in] Clicon handle 139 * @param[in] void*, eg Fastcgihandle request restconf 140 * @retval -1 Fatal error 141 * @retval 0 Credential not OK 142 * @retval 1 Credential OK 143 */ 144 typedef int (plgauth_t)(clicon_handle, void *); 145 146 typedef int (plgreset_t)(clicon_handle h, const char *db); /* Reset system status */ 147 148 /* Plugin statedata 149 * @param[in] Clicon handle 150 * @param[in] xpath Part of state requested 151 * @param[in] nsc XPATH namespace context. 152 * @param[in] xtop XML tree where statedata is added 153 * @retval -1 Fatal error 154 * @retval 0 OK 155 */ 156 typedef int (plgstatedata_t)(clicon_handle h, cvec *nsc, char *xpath, cxobj *xtop); 157 158 typedef void *transaction_data; 159 160 /* Transaction callback */ 161 typedef int (trans_cb_t)(clicon_handle h, transaction_data td); 162 163 /*! Hook to override default prompt with explicit function 164 * Format prompt before each getline 165 * @param[in] h Clicon handle 166 * @param[in] mode Cligen syntax mode 167 * @retval prompt Prompt to prepend all CLigen command lines 168 */ 169 typedef char *(cli_prompthook_t)(clicon_handle, char *mode); 170 171 /*! General-purpose datastore upgrade callback called once on startupo 172 * 173 * Gets called on startup after initial XML parsing, but before module-specific upgrades 174 * and before validation. 175 * @param[in] h Clicon handle 176 * @param[in] db Name of datastore, eg "running", "startup" or "tmp" 177 * @param[in] xt XML tree. Upgrade this "in place" 178 * @param[in] msd Info on datastore module-state, if any 179 * @retval -1 Error 180 * @retval 0 OK 181 */ 182 typedef int (datastore_upgrade_t)(clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd); 183 184 /*! Startup status for use in startup-callback 185 * Note that for STARTUP_ERR and STARTUP_INVALID, running runs in failsafe mode 186 * and startup contains the erroneous or invalid database. 187 * The user should repair the startup and 188 * (1) restart the backend 189 * (2) copy startup to candidate and commit. 190 */ 191 enum startup_status{ 192 STARTUP_ERR, /* XML/JSON syntax error */ 193 STARTUP_INVALID, /* XML/JSON OK, but (yang) validation fails */ 194 STARTUP_OK /* Everything OK (may still be modules-mismatch) */ 195 }; 196 197 /* plugin init struct for the api 198 * Note: Implicit init function 199 */ 200 struct clixon_plugin_api; 201 typedef struct clixon_plugin_api* (plginit2_t)(clicon_handle); /* Clixon plugin Init */ 202 203 struct clixon_plugin_api{ 204 /*--- Common fields. ---*/ 205 char ca_name[MAXPATHLEN]; /* Name of plugin (given by plugin) */ 206 plginit2_t *ca_init; /* Clixon plugin Init (implicit) */ 207 plgstart_t *ca_start; /* Plugin start */ 208 plgexit_t *ca_exit; /* Plugin exit */ 209 plgextension_t *ca_extension; /* Yang extension handler */ 210 union { 211 struct { /* cli-specific */ 212 cli_prompthook_t *ci_prompt; /* Prompt hook */ 213 cligen_susp_cb_t *ci_suspend; /* Ctrl-Z hook, see cligen getline */ 214 cligen_interrupt_cb_t *ci_interrupt; /* Ctrl-C, see cligen getline */ 215 } cau_cli; 216 struct { /* restconf-specific */ 217 plgauth_t *cr_auth; /* Auth credentials */ 218 } cau_restconf; 219 struct { /* netconf-specific */ 220 } cau_netconf; 221 struct { /* backend-specific */ 222 plgdaemon_t *cb_daemon; /* Plugin daemonized */ 223 plgreset_t *cb_reset; /* Reset system status */ 224 plgstatedata_t *cb_statedata; /* Get state data from plugin (backend only) */ 225 trans_cb_t *cb_trans_begin; /* Transaction start */ 226 trans_cb_t *cb_trans_validate; /* Transaction validation */ 227 trans_cb_t *cb_trans_complete; /* Transaction validation complete */ 228 trans_cb_t *cb_trans_commit; /* Transaction commit */ 229 trans_cb_t *cb_trans_commit_done; /* Transaction when commit done */ 230 trans_cb_t *cb_trans_revert; /* Transaction revert */ 231 trans_cb_t *cb_trans_end; /* Transaction completed */ 232 trans_cb_t *cb_trans_abort; /* Transaction aborted */ 233 datastore_upgrade_t *cb_datastore_upgrade; /* General-purpose datastore upgrade */ 234 } cau_backend; 235 } u; 236 }; 237 /* Access fields */ 238 #define ca_prompt u.cau_cli.ci_prompt 239 #define ca_suspend u.cau_cli.ci_suspend 240 #define ca_interrupt u.cau_cli.ci_interrupt 241 #define ca_auth u.cau_restconf.cr_auth 242 #define ca_daemon u.cau_backend.cb_daemon 243 #define ca_reset u.cau_backend.cb_reset 244 #define ca_statedata u.cau_backend.cb_statedata 245 #define ca_trans_begin u.cau_backend.cb_trans_begin 246 #define ca_trans_validate u.cau_backend.cb_trans_validate 247 #define ca_trans_complete u.cau_backend.cb_trans_complete 248 #define ca_trans_commit u.cau_backend.cb_trans_commit 249 #define ca_trans_commit_done u.cau_backend.cb_trans_commit_done 250 #define ca_trans_revert u.cau_backend.cb_trans_revert 251 #define ca_trans_end u.cau_backend.cb_trans_end 252 #define ca_trans_abort u.cau_backend.cb_trans_abort 253 #define ca_datastore_upgrade u.cau_backend.cb_datastore_upgrade 254 255 /* 256 * Macros 257 */ 258 #define upgrade_callback_register(h, cb, ns, arg) upgrade_callback_reg_fn((h), (cb), #cb, (ns), (arg)) 259 260 typedef struct clixon_plugin_api clixon_plugin_api; 261 262 /* Internal plugin structure with dlopen() handle and plugin_api 263 */ 264 struct clixon_plugin{ 265 char cp_name[MAXPATHLEN]; /* Plugin filename. Note api ca_name is given by plugin itself */ 266 plghndl_t cp_handle; /* Handle to plugin using dlopen(3) */ 267 clixon_plugin_api cp_api; 268 }; 269 typedef struct clixon_plugin clixon_plugin; 270 271 /* 272 * Prototypes 273 */ 274 275 /*! Plugin initialization function. Must appear in all plugins, not a clixon system function 276 * @param[in] h Clixon handle 277 * @retval api Pointer to API struct 278 * @retval NULL Failure (if clixon_err() called), module disabled otherwise. 279 * @see CLIXON_PLUGIN_INIT default symbol 280 */ 281 clixon_plugin_api *clixon_plugin_init(clicon_handle h); 282 283 clixon_plugin *clixon_plugin_each(clicon_handle h, clixon_plugin *cpprev); 284 285 clixon_plugin *clixon_plugin_each_revert(clicon_handle h, clixon_plugin *cpprev, int nr); 286 287 clixon_plugin *clixon_plugin_find(clicon_handle h, const char *name); 288 289 int clixon_plugins_load(clicon_handle h, const char *function, const char *dir, const char *regexp); 290 291 int clixon_pseudo_plugin(clicon_handle h, const char *name, clixon_plugin **cpp); 292 293 int clixon_plugin_start_one(clixon_plugin *cp, clicon_handle h); 294 int clixon_plugin_start_all(clicon_handle h); 295 296 int clixon_plugin_exit_one(clixon_plugin *cp, clicon_handle h); 297 int clixon_plugin_exit_all(clicon_handle h); 298 299 int clixon_plugin_auth_one(clixon_plugin *cp, clicon_handle h, void *arg); 300 int clixon_plugin_auth_all(clicon_handle h, void *arg); 301 302 int clixon_plugin_extension_one(clixon_plugin *cp, clicon_handle h, yang_stmt *yext, yang_stmt *ys); 303 int clixon_plugin_extension_all(clicon_handle h, yang_stmt *yext, yang_stmt *ys); 304 305 int clixon_plugin_datastore_upgrade_one(clixon_plugin *cp, clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd); 306 int clixon_plugin_datastore_upgrade_all(clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd); 307 308 /* rpc callback API */ 309 int rpc_callback_register(clicon_handle h, clicon_rpc_cb cb, void *arg, const char *ns, const char *name); 310 int rpc_callback_delete_all(clicon_handle h); 311 int rpc_callback_call(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg); 312 313 /* upgrade callback API */ 314 int upgrade_callback_reg_fn(clicon_handle h, clicon_upgrade_cb cb, const char *strfn, const char *ns, void *arg); 315 int upgrade_callback_delete_all(clicon_handle h); 316 int upgrade_callback_call(clicon_handle h, cxobj *xt, char *ns, uint16_t op, uint32_t from, uint32_t to, cbuf *cbret); 317 318 #endif /* _CLIXON_PLUGIN_H_ */ 319