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