1 | /***************************************
2 | $Revision: 1.5 $
3 |
4 | Error reporting (er) er_macro.c - simple macro processor
5 |
6 | Status: NOT REVUED, PARTLY TESTED
7 |
8 | Design and implementation by: Marek Bukowy
9 |
10 | ******************/ /******************
11 | Copyright (c) 1999,2000 RIPE NCC
12 |
13 | All Rights Reserved
14 |
15 | Permission to use, copy, modify, and distribute this software and its
16 | documentation for any purpose and without fee is hereby granted,
17 | provided that the above copyright notice appear in all copies and that
18 | both that copyright notice and this permission notice appear in
19 | supporting documentation, and that the name of the author not be
20 | used in advertising or publicity pertaining to distribution of the
21 | software without specific, written prior permission.
22 |
23 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
25 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
26 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
28 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 | ***************************************/
30 |
31 | #include <string.h>
32 | #include <glib.h>
33 | #include "stubs.h"
34 | #include "sk.h"
35 | #include "er_macro.h"
36 | #include "er_paths.h"
37 | #include "er_yacc_helper.h"
38 | #include "memwrap.h"
39 |
40 | #include "ca_configFns.h"
41 | #include "ca_dictSyms.h"
42 | #include "ca_macros.h"
43 |
44 | GHashTable *er_macro_hash = NULL;
45 |
46 | /* process a macro call, i.e. execute one of the predefined macros
47 | selected by the 0th argument, using other arguments.
48 |
49 | Uses the er_macro_array[] to find the macro definition.
50 |
51 | Allocates the result string and stores the pointer to it in **output.
52 |
53 | returns 0 on success, non-0 on failure.
54 | */
55 |
56 | int
57 | ER_process_split(int argc, char **argv, char **output)
58 | {
59 | char *pattern, *ch;
60 | GString *result = g_string_new("");
61 |
62 | dieif( argc == 0 ); /* may not be called without the macro name */
63 |
64 | /* find macro, error if not found */
65 | if( (pattern = g_hash_table_lookup(er_macro_hash, argv[0])) == NULL ) {
66 | return -1;
67 | }
68 |
69 | /* copy the macro definition by portions, substituting the $([0-9])
70 | entries with arguments. Error if not enough arguments.
71 | */
72 | do {
73 |
74 | if( (ch = strstr( pattern, "$(" )) == NULL ) {
75 | /* no more entries. copy the rest */
76 | g_string_append ( result, pattern );
77 | break;
78 | }
79 | else {
80 | /* pass the string between here and ch */
81 | while( pattern != ch ) {
82 | g_string_append_c ( result, *pattern );
83 | pattern++;
84 | }
85 | /* check the next 3 characters exist, break the look if not */
86 | if( *(ch+2) == '\0' || *(ch+3) == '\0') {
87 | break;
88 | }
89 |
90 | /* look for the digit and ")", pass the $( through if not present */
91 | if( ! isdigit(*(ch+2)) || *(ch+3) != ')' ) {
92 | /* not need to do anything to make it pass through */
93 | ;
94 | }
95 | else {
96 | /* substitute the $(?) with the appropriate argument.
97 | error if not enough arguments or $(0) is used.*/
98 | int a = *(ch+2) - '0';
99 |
100 | if( argc < a || a==0) {
101 | return -1;
102 | }
103 | g_string_append( result, argv[a]);
104 | /* advance the pattern pointer */
105 | pattern += strlen("$(1)");
106 | }
107 | }
108 | } while(1);
109 |
110 | /* copy the pointer, free the orig structure, keep the text */
111 |
112 | *output = (result->str);
113 |
114 | g_string_free( result, FALSE );
115 |
116 | return 0;
117 | }
118 |
119 |
120 | /* wrapper around the above that splits the string into argv
121 | and calls the ER_parse.
122 |
123 | sets the errbuf to the ER_parse_spec result
124 |
125 | returns 0 on success, non-0 on failure.
126 | */
127 | int
128 | ER_macro_spec(char *input, char **errbuf)
129 | {
130 | char **argv = g_strsplit(input, " ", 0);
131 | int argc = 0, ret;
132 | char *fullspec;
133 |
134 | while( argv[argc] != NULL ) {
135 | argc++;
136 | }
137 |
138 |
139 | if( ER_process_split(argc, argv, &fullspec) != 0 ) {
140 | /* macro unknown. That's OK, just parse that text now */
141 |
142 | fullspec = strdup(input);
143 | }
144 |
145 | ret = ER_parse_spec(fullspec, errbuf);
146 |
147 | free(fullspec);
148 | g_strfreev(argv);
149 | return ret;
150 |
151 | }
152 |
153 |
154 | void
155 | ER_make_macro(char *name, char *def)
156 | {
157 | char *cp_name = wr_string(name);
158 | char *cp_def = wr_string(def);
159 |
160 | void *oldkey, *oldval;
161 |
162 | /* cleanup on redefinition */
163 | if( g_hash_table_lookup_extended(er_macro_hash, name,
164 | &oldkey, &oldval) == TRUE ) {
165 | g_hash_table_remove(er_macro_hash, name);
166 | wr_free(oldkey);
167 | wr_free(oldval);
168 | }
169 |
170 | g_hash_table_insert(er_macro_hash, cp_name, cp_def);
171 | }
172 |
173 |
174 | /* predefine some macros */
175 | void
176 | ER_macro_predef(void)
177 | {
178 | /* create the hash with hashing and equality testing functions
179 | specific for strings
180 | */
181 | er_macro_hash = g_hash_table_new(g_str_hash, g_str_equal);
182 |
183 | #define DBUPDLOG_FORMAT " FORMAT SEVCHAR|FACSYMB|TEXTLONG|DATETIME|PIDFULL|PROGNAME|MNEMONIC "
184 | #define RIPLOG_FORMAT " FORMAT SEVCHAR|FACSYMB|TEXTLONG|DATETIME|PIDFULL|PROGNAME|THR_ID|MNEMONIC "
185 |
186 | /* catch-all for dbupdate */
187 | ER_make_macro("DBUPERR", "CREATE dbuperr {"
188 | DBUPDLOG_FORMAT "NAME $(1) DATE}"
189 | " ( FAC MM|UP SEV W- )");
190 |
191 | /* catch-all for rip */
192 | ER_make_macro("ALLRIPERR", "CREATE allriperr { "
193 | RIPLOG_FORMAT "NAME $(1) DATE}"
194 | " (FAC ALL SEV W- )");
195 |
196 | /* selected: errors in ripupdate */
197 | ER_make_macro("RIPUPERR", "CREATE ripuperr {"
198 | RIPLOG_FORMAT "NAME $(1) DATE}"
199 | " (FAC UD SEV W- )");
200 |
201 | /* querylog: logs all rip queries */
202 | ER_make_macro("QRYLOG", "CREATE qrylog {"
203 | RIPLOG_FORMAT "NAME $(1) DATE}"
204 | " (FAC PW ASP PW_I_QRYLOG SEV I )");
205 |
206 | /* audit: any security related messages from RIP */
207 | ER_make_macro("RIPAUDIT", "CREATE ripaudit {"
208 | RIPLOG_FORMAT "NAME $(1) DATE}"
209 | "( FAC PW ASP PW_I_PASSUN SEV i )"
210 | " ( FAC AC ASP AC_I_PERMBAN SEV I )");
211 |
212 | /* ripupdlog: logs all update transactions */
213 | ER_make_macro("RIPUPDLOG", "CREATE ripupdlog_$(2) {"
214 | RIPLOG_FORMAT "NAME $(1)_$(2) DATE}"
215 | " ( FAC UD ASP 0xffffffff SEV I THR self)");
216 |
217 | /* ripmirlog */
218 | ER_make_macro("RIPMIRLOG", "CREATE ripmirlog {"
219 | RIPLOG_FORMAT "NAME $(1) DATE }"
220 | "( FAC PM ASP 0xffffffff SEV I )");
221 |
222 | /* server log: all administration by SV (startup, shutdown, etc) and errors */
223 | ER_make_macro("RIPSVRLOG", "CREATE ripsvrlog {"
224 | RIPLOG_FORMAT "NAME $(1) DATE}"
225 | " ( FAC SV ASP 0xffffffff SEV I-F )");
226 | /* dbase log: all errors of SQ */
227 | ER_make_macro("SQLOG", " CREATE sqlog {"
228 | RIPLOG_FORMAT "NAME $(1) DATE}"
229 | " ( FAC SQ SEV W- )");
230 |
231 | }
232 |
233 | static
234 | void er_macro_list_hook (void* key, void * value, void *condat)
235 | {
236 | SK_cd_printf(condat, "%s: %s\n", (char *) key, (char *) value);
237 | }
238 |
239 | void
240 | ER_macro_list(sk_conn_st *condat)
241 | {
242 | g_hash_table_foreach(er_macro_hash, er_macro_list_hook, condat );
243 | }
244 |
245 | /* override macros with the definitions from the config file */
246 | void
247 | ER_proc_ca_macro(void)
248 | {
249 | char *alldef = ca_get_er_macro ;
250 | char *this_line = alldef;
251 | char *defname, *defbody, *end_line;
252 |
253 | /* alldef is a copy of the configured value. so we can modify it
254 | if it helps us to do it line by line */
255 |
256 | /* ER_MACRO may not be present in the configuration, in which case
257 | ca_get_er_macro returns NULL */
258 |
259 | if( alldef != NULL ) {
260 |
261 | while( *this_line != '\0' ) {
262 | /* separate the line */
263 | end_line = strchr(this_line, '\n');
264 | *end_line = '\0';
265 |
266 | /* advance to non-whitespace */
267 | while( isspace(*this_line) ) {
268 | this_line++;
269 | }
270 |
271 | /* find the name and body of the definition */
272 | defname = strsep(&this_line, " \t");
273 | defbody = this_line;
274 |
275 | /* fire */
276 | dieif( defname == NULL || defbody == NULL );
277 | ER_make_macro( defname, defbody );
278 |
279 | this_line = end_line + 1;
280 | }
281 |
282 | free(alldef);
283 | }
284 | }
285 |
286 |
287 | /* process the error definitions from the config file */
288 | void
289 | ER_proc_ca_err(void)
290 | {
291 | char *alldef = ca_get_er_def ;
292 | char *this_line = alldef;
293 | char *defname, *defbody, *end_line;
294 | char *erret = NULL;
295 | int res;
296 |
297 | /* alldef is a copy of the configured value. so we can modify it
298 | if it helps us to do it line by line */
299 |
300 | /* ER_DEF may not be present in the configuration, in which case
301 | ca_get_er_def returns NULL */
302 | if( alldef != NULL ) {
303 |
304 | while( *this_line != '\0' ) {
305 | /* separate the line */
306 | end_line = strchr(this_line, '\n');
307 | *end_line = '\0';
308 |
309 | /* fire */
310 | if( (res = ER_macro_spec(this_line, &erret)) != 0 ) {
311 | fputs(erret, stderr);
312 | die;
313 | }
314 |
315 | free(erret);
316 |
317 | this_line = end_line + 1;
318 | }
319 |
320 | free(alldef);
321 | }
322 | }