3
* Implementation of the schedule MIB config handling
6
#include <net-snmp/net-snmp-config.h>
7
#include <net-snmp/net-snmp-includes.h>
8
#include <net-snmp/agent/net-snmp-agent-includes.h>
10
#include "disman/schedule/schedCore.h"
11
#include "disman/schedule/schedConf.h"
13
static int schedEntries;
15
/** Initializes the schedConf module */
19
DEBUGMSGTL(("disman:schedule:init", "Initializing config module\n"));
20
init_schedule_container();
23
* Register public configuration directives
25
snmpd_register_config_handler("repeat", parse_sched_periodic, NULL,
26
"repeat period OID = value");
27
snmpd_register_config_handler("cron", parse_sched_timed, NULL,
28
"cron * * * * * OID = value");
29
snmpd_register_config_handler("at", parse_sched_timed, NULL,
30
"at * * * * * OID = value");
33
* Register internal configuration directive,
34
* and arrange for dynamically configured entries to be saved
36
snmpd_register_config_handler("_schedTable", parse_schedTable, NULL, NULL);
37
snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
38
store_schedTable, NULL);
43
/* =======================================================
45
* Handlers for user-configured (static) scheduled actions
47
* ======================================================= */
50
parse_sched_periodic( const char *token, char *line )
52
netsnmp_tdata_row *row;
53
struct schedTable_entry *entry;
58
oid variable[ MAX_OID_LEN], *var_ptr = variable;
59
size_t var_len = MAX_OID_LEN;
62
sprintf(buf, "_conf%03d", schedEntries);
64
DEBUGMSGTL(( "disman:schedule:conf", "periodic: %s %s\n", token, line));
66
* Parse the configure directive line
68
line = read_config_read_data(ASN_INTEGER, line, &frequency, &tmpint);
69
line = read_config_read_data(ASN_OBJECT_ID, line, &var_ptr, &var_len);
71
config_perror("invalid specification for schedVariable");
75
* Skip over optional assignment in "var = value"
77
while (line && isspace(*line))
79
if (line && *line == '=' ) {
81
while (line && isspace(*line)) {
85
line = read_config_read_data(ASN_INTEGER, line, &value, &tmpint);
88
* Create an entry in the schedTable
90
row = schedTable_createEntry( "snmpd.conf", buf );
91
if (!row || !row->data) {
92
config_perror("create schedule entry failure");
95
entry = (struct schedTable_entry *)row->data;
97
entry->schedInterval = frequency;
98
entry->schedValue = value;
99
entry->schedVariable_len = var_len;
100
memcpy(entry->schedVariable, variable, var_len*sizeof(oid));
102
entry->schedType = SCHED_TYPE_PERIODIC;
103
entry->schedStorageType = ST_READONLY; /* or PERMANENT */
104
entry->flags = SCHEDULE_FLAG_ENABLED |
105
SCHEDULE_FLAG_ACTIVE |
107
entry->session = netsnmp_query_get_default_session();
108
sched_nextTime( entry );
113
* Timed-schedule utility:
114
* Convert from a cron-style specification to the equivalent set
115
* of bits. Note that minute, hour and weekday crontab fields are
116
* 0-based, while day and month more naturally start from 1.
119
_sched_convert_bits( char *cron_spec, char *bit_buf,
120
int bit_buf_len, int max_val, int startAt1 ) {
121
char *cp = cron_spec;
122
char b[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
123
int val, major, minor;
126
if (!cron_spec || !bit_buf)
130
* Wildcard field - set all bits
133
memset( bit_buf, 0xff, bit_buf_len );
136
* An "all-bits" specification may not be an exact multiple of 8.
137
* Work out how far we've overshot things, and tidy up the excess.
139
overshoot = 8*bit_buf_len-max_val;
140
while ( overshoot > 0 ) {
141
bit_buf[ bit_buf_len-1 ] ^= b[8-overshoot];
148
* Otherwise, clear the bit string buffer,
149
* and start calculating which bits to set
151
memset( bit_buf, 0, bit_buf_len );
154
sscanf( cp, "%d", &val);
155
/* Handle negative day specification */
163
bit_buf[ major ] |= b[minor];
165
/* XXX - ideally we should handle "X-Y" syntax as well */
166
while (*cp && *cp!=',')
175
parse_sched_timed( const char *token, char *line )
177
netsnmp_tdata_row *row;
178
struct schedTable_entry *entry;
181
char minConf[512]; size_t min_len = sizeof(minConf); char minVal[8];
182
char hourConf[512]; size_t hour_len = sizeof(hourConf); char hourVal[3];
183
char dateConf[512]; size_t date_len = sizeof(dateConf); char dateVal[8];
184
char monConf[512]; size_t mon_len = sizeof(monConf); char monVal[2];
185
char dayConf[512]; size_t day_len = sizeof(dayConf); char dayVal;
189
oid variable[ MAX_OID_LEN], *var_ptr = variable;
190
size_t var_len = MAX_OID_LEN;
193
sprintf(buf, "_conf%03d", schedEntries);
195
DEBUGMSGTL(( "sched", "config: %s %s\n", token, line));
197
* Parse the configure directive line
200
line = read_config_read_data(ASN_OCTET_STR, line, &cp, &min_len);
202
line = read_config_read_data(ASN_OCTET_STR, line, &cp, &hour_len);
204
line = read_config_read_data(ASN_OCTET_STR, line, &cp, &date_len);
206
line = read_config_read_data(ASN_OCTET_STR, line, &cp, &mon_len);
208
line = read_config_read_data(ASN_OCTET_STR, line, &cp, &day_len);
210
config_perror("invalid schedule time specification");
214
line = read_config_read_data(ASN_OBJECT_ID, line, &var_ptr, &var_len);
216
config_perror("invalid specification for schedVariable");
220
* Skip over optional assignment in "var = value"
222
while (line && isspace(*line))
224
if ( *line == '=' ) {
226
while (line && isspace(*line)) {
230
line = read_config_read_data(ASN_INTEGER, line, &value, &tmpint);
233
* Convert from cron-style specifications into bits
235
_sched_convert_bits( minConf, minVal, 8, 60, 0 );
236
_sched_convert_bits( hourConf, hourVal, 3, 24, 0 );
237
memset(dateVal+4, 0, 4); /* Clear the reverse day bits */
238
_sched_convert_bits( dateConf, dateVal, 4, 31, 1 );
239
_sched_convert_bits( monConf, monVal, 2, 12, 1 );
240
_sched_convert_bits( dayConf, &dayVal, 1, 8, 0 );
241
if ( dayVal & 0x01 ) { /* sunday(7) = sunday(0) */
247
* Create an entry in the schedTable
249
row = schedTable_createEntry("snmpd.conf", buf);
250
if (!row || !row->data) {
251
config_perror("create schedule entry failure");
254
entry = (struct schedTable_entry *)row->data;
256
entry->schedWeekDay = dayVal;
257
memcpy(entry->schedMonth, monVal, 2);
258
memcpy(entry->schedDay, dateVal, 4+4);
259
memcpy(entry->schedHour, hourVal, 3);
260
memcpy(entry->schedMinute, minVal, 8);
262
memcpy(entry->schedVariable, variable, var_len*sizeof(oid));
263
entry->schedVariable_len = var_len;
264
entry->schedValue = value;
266
if ( !strcmp( token, "at" ))
267
entry->schedType = SCHED_TYPE_ONESHOT;
269
entry->schedType = SCHED_TYPE_CALENDAR;
270
entry->schedStorageType = ST_READONLY; /* or PERMANENT */
271
entry->flags = SCHEDULE_FLAG_ENABLED |
272
SCHEDULE_FLAG_ACTIVE |
274
entry->session = netsnmp_query_get_default_session();
275
sched_nextTime( entry );
279
/* ========================================
281
* Handlers for persistent schedule entries
283
* ======================================== */
286
parse_schedTable( const char *token, char *line )
288
char owner[SCHED_STR1_LEN+1];
289
char name[ SCHED_STR1_LEN+1];
290
char time_bits[22]; /* schedWeekDay..schedMinute */
293
netsnmp_tdata_row *row;
294
struct schedTable_entry *entry;
296
DEBUGMSGTL(("disman:schedule:conf", "Parsing schedTable config... "));
299
* Read in the index information for this entry
300
* and create a (non-fixed) data structure for it.
302
memset( owner, 0, sizeof(owner));
303
memset( name, 0, sizeof(name));
304
len = SCHED_STR1_LEN; vp = owner;
305
line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
306
len = SCHED_STR1_LEN; vp = name;
307
line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
308
row = schedTable_createEntry(owner, name);
309
if (!row || !row->data) {
310
config_perror("create schedule entry failure");
313
entry = (struct schedTable_entry *)row->data;
314
DEBUGMSG(("disman:schedule:conf", "(%s, %s) ", owner, name));
317
* Read in the column values.
319
len = SCHED_STR2_LEN; vp = entry->schedDescr;
320
line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
321
line = read_config_read_data(ASN_UNSIGNED, line,
322
&entry->schedInterval, NULL);
323
/* Unpick the various timed bits */
324
len = 22; vp = time_bits;
325
line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
326
entry->schedWeekDay = time_bits[0];
327
entry->schedMonth[0] = time_bits[1];
328
entry->schedMonth[1] = time_bits[2];
329
entry->schedHour[0] = time_bits[11];
330
entry->schedHour[1] = time_bits[12];
331
entry->schedHour[2] = time_bits[13];
332
memcpy(entry->schedDay, time_bits+3, 8);
333
memcpy(entry->schedMinute, time_bits+14, 8);
335
len = SCHED_STR1_LEN; vp = entry->schedContextName;
336
line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
337
len = MAX_OID_LEN; vp = entry->schedVariable;
338
line = read_config_read_data(ASN_OBJECT_ID, line, &vp, &len);
339
entry->schedVariable_len = len;
340
line = read_config_read_data(ASN_INTEGER, line,
341
&entry->schedValue, NULL);
342
line = read_config_read_data(ASN_UNSIGNED, line,
343
&entry->schedType, NULL);
344
line = read_config_read_data(ASN_UNSIGNED, line, &len, NULL);
345
entry->flags |= (len /* & WHAT ?? */);
346
/* XXX - Will need to read in the 'iquery' access information */
347
entry->flags |= SCHEDULE_FLAG_VALID;
349
DEBUGMSG(("disman:schedule:conf", "\n"));
353
* Save dynamically-configured schedTable entries into persistent storage
356
store_schedTable(int majorID, int minorID, void *serverarg, void *clientarg)
358
char line[SNMP_MAXBUF];
359
char time_bits[22]; /* schedWeekDay..schedMinute */
363
netsnmp_tdata_row *row;
364
struct schedTable_entry *entry;
367
DEBUGMSGTL(( "disman:schedule:conf", "Storing schedTable:\n"));
369
for (row = netsnmp_tdata_row_first( schedule_table );
371
row = netsnmp_tdata_row_next( schedule_table, row )) {
375
entry = (struct schedTable_entry *)row->data;
378
* Only save (dynamically-created) 'nonVolatile' entries
379
* (XXX - what about dynamic 'permanent' entries ??)
381
if (entry->schedStorageType != ST_NONVOLATILE )
383
DEBUGMSGTL(( "disman:schedule:conf", " Storing (%s, %s)\n",
384
entry->schedOwner, entry->schedName));
386
memset(line, 0, sizeof(line));
387
strcpy(line, "_schedTable ");
388
cptr = line + strlen(line);
390
vp = entry->schedOwner; tint = strlen( vp );
391
cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint );
392
vp = entry->schedName; tint = strlen( vp );
393
cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint );
394
vp = entry->schedDescr; tint = strlen( vp );
395
cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint );
396
tint = entry->schedInterval;
397
cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL );
399
/* Combine all the timed bits into a single field */
400
time_bits[0] = entry->schedWeekDay;
401
time_bits[1] = entry->schedMonth[0];
402
time_bits[2] = entry->schedMonth[1];
403
time_bits[11] = entry->schedHour[0];
404
time_bits[12] = entry->schedHour[1];
405
time_bits[13] = entry->schedHour[2];
406
memcpy(time_bits+3, entry->schedDay, 8);
407
memcpy(time_bits+14, entry->schedMinute, 8);
408
vp = time_bits; tint = 22;
409
cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint );
411
vp = entry->schedContextName; tint = strlen( vp );
412
cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint );
413
vp = entry->schedVariable;
414
tint = entry->schedVariable_len;
415
cptr = read_config_store_data(ASN_OBJECT_ID, cptr, &vp, &tint );
416
tint = entry->schedValue;
417
cptr = read_config_store_data(ASN_INTEGER, cptr, &tint, NULL );
418
tint = entry->schedType;
419
cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL );
420
tint = entry->flags /* & WHAT ?? */;
421
cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL );
422
/* XXX - Need to store the 'iquery' access information */
423
snmpd_store_config(line);
425
DEBUGMSGTL(( "disman:schedule:conf", " done.\n"));
426
return SNMPERR_SUCCESS;