114
104
* if there is no container, bail. otherwise, register the callbacks
115
105
* for persistent storage.
117
if (NULL == _ifXTable_container_get())
118
return; /* msg already logged */
120
register_config_handler(NULL, "ifXTable", _ifXTable_restore, NULL,
122
rc = snmp_register_callback(SNMP_CALLBACK_LIBRARY,
123
SNMP_CALLBACK_STORE_DATA, _ifXTable_save,
124
_ifXTable_container_get());
125
if (rc != SNMP_ERR_NOERROR)
126
snmp_log(LOG_ERR, "error registering for STORE_DATA callback "
127
"in initialize_table_ifXTable\n");
107
if (NULL == ifTable_container_get())
108
return; /* msg already logged */
129
110
} /* initialize_table_ifXTable */
132
* extra context initialization
113
* extra context initialization (eg default values)
134
115
* @param rowreq_ctx : row request context
135
116
* @param user_init_ctx : void pointer for user (parameter to rowreq_ctx_allocate)
198
199
* post-request callback
202
* New rows have been inserted into the container, and
203
* deleted rows have been removed from the container and
206
* @param user_context
207
* @param rc : MFD_SUCCESS if all requests succeeded
201
209
* @retval MFD_SUCCESS : success.
202
210
* @retval MFD_ERROR : other error (ignored)
205
ifXTable_post_request(ifXTable_registration_ptr user_context)
213
ifXTable_post_request(ifXTable_registration * user_context, int rc)
207
215
DEBUGMSGTL(("verbose:ifXTable:ifXTable_post_request", "called\n"));
210
* TODO:511:o: Perform ifXTable pos-request actions.
218
* TODO:511:o: Perform ifXTable post-request actions.
222
* check to set if any rows were changed.
224
if (ifXTable_dirty_get()) {
226
* check if request was successful. If so, this would be
227
* a good place to save data to its persistent store.
229
if (MFD_SUCCESS == rc) {
231
* save changed rows, if you haven't already
233
snmp_store(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
234
NETSNMP_DS_LIB_APPTYPE));
237
ifXTable_dirty_set(0); /* clear table dirty flag */
213
240
return MFD_SUCCESS;
214
241
} /* ifXTable_post_request */
374
408
* TODO:231:o: |-> Extract the current value of the ifName data.
375
* set (* ifName_val_ptr_ptr ) and (* ifName_val_ptr_len_ptr ) from rowreq_ctx->data
409
* copy (* ifName_val_ptr_ptr ) data and (* ifName_val_ptr_len_ptr ) from rowreq_ctx->data
378
412
* make sure there is enough space for ifName data
380
414
tmp_len = strlen(rowreq_ctx->data.ifName);
381
if ((NULL == (*ifName_val_ptr_ptr))
382
|| ((*ifName_val_ptr_len_ptr) < tmp_len)) {
415
if ((NULL == (*ifName_val_ptr_ptr)) ||
416
((*ifName_val_ptr_len_ptr) < tmp_len)) {
384
418
* allocate space for ifName data
386
(*ifName_val_ptr_ptr) =
387
malloc(tmp_len * sizeof((*ifName_val_ptr_ptr)[0]));
420
(*ifName_val_ptr_ptr) = malloc(tmp_len);
388
421
if (NULL == (*ifName_val_ptr_ptr)) {
389
422
snmp_log(LOG_ERR, "could not allocate memory\n");
390
423
return MFD_ERROR;
393
426
(*ifName_val_ptr_len_ptr) = tmp_len;
394
memcpy((*ifName_val_ptr_ptr), rowreq_ctx->data.ifName,
395
(*ifName_val_ptr_len_ptr) * sizeof((*ifName_val_ptr_ptr)[0]));
427
memcpy((*ifName_val_ptr_ptr), rowreq_ctx->data.ifName, tmp_len);
397
429
return MFD_SUCCESS;
398
430
} /* ifName_get */
1440
1472
* TODO:231:o: |-> Extract the current value of the ifAlias data.
1441
* set (* ifAlias_val_ptr_ptr ) and (* ifAlias_val_ptr_len_ptr ) from rowreq_ctx->data
1473
* copy (* ifAlias_val_ptr_ptr ) data and (* ifAlias_val_ptr_len_ptr ) from rowreq_ctx->data
1444
1476
* make sure there is enough space for ifAlias data
1446
if ((NULL == (*ifAlias_val_ptr_ptr))
1447
|| ((*ifAlias_val_ptr_len_ptr) < rowreq_ctx->data.ifAlias_len)) {
1478
if ((NULL == (*ifAlias_val_ptr_ptr)) ||
1479
((*ifAlias_val_ptr_len_ptr) <
1480
(rowreq_ctx->data.ifAlias_len *
1481
sizeof(rowreq_ctx->data.ifAlias[0])))) {
1449
1483
* allocate space for ifAlias data
1451
1485
(*ifAlias_val_ptr_ptr) =
1452
1486
malloc(rowreq_ctx->data.ifAlias_len *
1453
sizeof((*ifAlias_val_ptr_ptr)[0]));
1487
sizeof(rowreq_ctx->data.ifAlias[0]));
1454
1488
if (NULL == (*ifAlias_val_ptr_ptr)) {
1455
1489
snmp_log(LOG_ERR, "could not allocate memory\n");
1456
1490
return MFD_ERROR;
1459
(*ifAlias_val_ptr_len_ptr) = rowreq_ctx->data.ifAlias_len;
1493
(*ifAlias_val_ptr_len_ptr) =
1494
rowreq_ctx->data.ifAlias_len * sizeof(rowreq_ctx->data.ifAlias[0]);
1460
1495
memcpy((*ifAlias_val_ptr_ptr), rowreq_ctx->data.ifAlias,
1461
(*ifAlias_val_ptr_len_ptr) * sizeof((*ifAlias_val_ptr_ptr)[0]));
1496
rowreq_ctx->data.ifAlias_len *
1497
sizeof(rowreq_ctx->data.ifAlias[0]));
1463
1499
return MFD_SUCCESS;
1464
1500
} /* ifAlias_get */
1646
1682
* TODO:451:M: |-> Setup ifXTable undo.
1647
1683
* set up ifXTable undo information, in preparation for a set.
1684
* Undo storage is in (* ifCounterDiscontinuityTime_val_ptr )*
1688
} /* ifXTable_undo_setup */
1691
* Undo a set request.
1693
* This function will be called before the individual node undo
1694
* functions are called. If you need to do any undo that is not
1695
* related to a specific column, you can do it here.
1697
* Note that an individual node's undo function will only be called
1698
* if that node is being set to a new value.
1700
* If there is anything specific to a particular column (e.g. releasing
1701
* memory for a string), you should do that setup in the node's undo
1702
* function, so it won't be done unless it is necessary.
1705
* Pointer to the table context (ifXTable_rowreq_ctx)
1707
* @retval MFD_SUCCESS : success
1708
* @retval MFD_ERROR : error. set will fail.
1711
ifXTable_undo(ifXTable_rowreq_ctx * rowreq_ctx)
1713
int rc = MFD_SUCCESS;
1715
DEBUGMSGTL(("verbose:ifXTable:ifXTable_undo", "called\n"));
1717
/** we should have a non-NULL pointer */
1718
netsnmp_assert(NULL != rowreq_ctx);
1721
* TODO:451:M: |-> ifXTable undo.
1722
* ifXTable undo information, in response to a failed set.
1723
* Undo storage is in (* ifCounterDiscontinuityTime_val_ptr )*
1731
1808
* nothing needs to be done. That leaves ifPromiscuosMode,
1732
1809
* which I'm leery about implementing. Thus, at this point,
1733
1810
* there is nothing to do except twiddle flag bits.
1735
* in keeping with the net-snmp persistence policy, changes are kept
1736
* in memory, and saved to disk when the agent shuts down.
1738
if (save_flags & FLAG_IFLINKUPDOWNTRAPENABLE) {
1739
save_flags &= ~FLAG_IFLINKUPDOWNTRAPENABLE; /* clear ifLinkUpDownTrapEnable */
1812
if (save_flags & COLUMN_IFLINKUPDOWNTRAPENABLE_FLAG) {
1813
save_flags &= ~COLUMN_IFLINKUPDOWNTRAPENABLE_FLAG; /* clear ifLinkUpDownTrapEnable */
1741
1815
* TODO:482:o: |-> commit column ifLinkUpDownTrapEnable.
1744
1818
* set flag, in case we need to undo ifLinkUpDownTrapEnable
1746
rowreq_ctx->column_set_flags |= FLAG_IFLINKUPDOWNTRAPENABLE;
1820
rowreq_ctx->column_set_flags |= COLUMN_IFLINKUPDOWNTRAPENABLE_FLAG;
1749
if (save_flags & FLAG_IFPROMISCUOUSMODE) {
1750
save_flags &= ~FLAG_IFPROMISCUOUSMODE; /* clear ifPromiscuousMode */
1751
1822
#ifdef NETSNMP_ENABLE_PROMISCUOUSMODE_SET
1823
if (save_flags & COLUMN_IFPROMISCUOUSMODE_FLAG) {
1824
save_flags &= ~COLUMN_IFPROMISCUOUSMODE_FLAG; /* clear ifPromiscuousMode */
1753
1826
* TODO:482:o: |-> commit column ifPromiscuousMode.
1815
1892
* check the column's flag in rowreq_ctx->column_set_flags to see
1816
1893
* if it was set during commit, then undo it.
1818
* eg: if (rowreq_ctx->column_set_flags & FLAG_) {}
1895
* eg: if (rowreq_ctx->column_set_flags & COLUMN__FLAG) {}
1900
* if we successfully un-commited this row, clear the dirty flag.
1902
if (MFD_SUCCESS == rc) {
1903
rowreq_ctx->rowreq_flags &= ~MFD_ROW_DIRTY;
1822
1907
} /* ifXTable_undo_commit */
1825
* TODO:420:r: Implement ifXTable index validation.
1827
/*---------------------------------------------------------------------
1828
* IF-MIB::ifEntry.ifIndex
1829
* ifIndex is subid 1 of ifEntry.
1830
* Its status is Current, and its access level is ReadOnly.
1831
* OID: .1.3.6.1.2.1.2.2.1.1
1833
A unique value, greater than zero, for each interface. It
1834
is recommended that values are assigned contiguously
1835
starting from 1. The value for each interface sub-layer
1836
must remain constant at least from one re-initialization of
1837
the entity's network management system to the next re-
1841
* accessible 1 isscalar 0 enums 0 hasdefval 0
1842
* readable 1 iscolumn 1 ranges 1 hashint 1
1846
* Ranges: 1 - 2147483647;
1848
* Its syntax is InterfaceIndex (based on perltype INTEGER32)
1849
* The net-snmp type is ASN_INTEGER. The C type decl is long (long)
1852
1910
* TODO:440:M: Implement ifXTable node value checks.
1853
1911
* TODO:450:M: Implement ifXTable undo functions.
1854
1912
* TODO:460:M: Implement ifXTable set functions.
2467
_ifXTable_row_save(ifXTable_rowreq_ctx * rowreq_ctx, void *type)
2472
netsnmp_assert(NULL != rowreq_ctx);
2475
* allocate space for data. Remeber, data will be stored in
2476
* ASCII form, so you need to allow for that. Here are some
2477
* general guidelines:
2479
* Object ID : 12 * len (ASCII len of max int + 1 for .)
2480
* Octet String: (2 * len) + 2 (2 ASCII chars per byte + "0x")
2481
* Integers : 12 (ASCII len for smallest negative number)
2483
size = sizeof(row_token) + 1 + /* 'ifXTable ' */
2484
13 + /* ifIndex value + ' ' */
2485
13 + /* col #, + ':' */
2486
(rowreq_ctx->data.ifAlias_len * 2) + 2 + /* [0|1] + ' ' */
2487
4; /* '\n\0' & possible quoting */
2490
* allocate memory for the line
2492
line = buf = calloc(1, size);
2494
snmp_log(LOG_ERR, "error allocating memory while saving row\n");
2495
return SNMP_ERR_GENERR;
2501
buf += sprintf(buf, "%s ", row_token);
2502
buf = read_config_save_objid(buf, rowreq_ctx->oid_idx.oids,
2503
rowreq_ctx->oid_idx.len);
2505
snmp_log(LOG_ERR, "error saving row to persistent file\n");
2507
return SNMP_ERR_GENERR;
2512
* prefix with column number, so we don't ever depend on
2515
buf += sprintf(buf, "%u:", COLUMN_IFALIAS);
2516
buf = read_config_save_octet_string(buf, rowreq_ctx->data.ifAlias,
2517
rowreq_ctx->data.ifAlias_len);
2521
* prefix with column number, so we don't ever depend on
2524
buf += sprintf(buf, "%u:%1lu ", COLUMN_IFLINKUPDOWNTRAPENABLE,
2525
rowreq_ctx->data.ifLinkUpDownTrapEnable);
2528
* terminate and store the line
2530
sprintf(buf, "%c\n", LINE_TERM_CHAR);
2531
DEBUGMSGTL(("ifXTable:save", "saving line '%s'\n", line));
2532
read_config_store((char *) type, line);
2539
return SNMP_ERR_NOERROR;
2544
_ifXTable_save(int majorID, int minorID, void *serverarg, void *clientarg)
2546
char *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
2547
NETSNMP_DS_LIB_APPTYPE);
2552
CONTAINER_FOR_EACH((netsnmp_container *) clientarg,
2553
(netsnmp_container_obj_func *)
2554
_ifXTable_row_save, appname);
2559
return SNMPERR_SUCCESS;
2564
_ifXTable_restore(const char *token, char *buf)
2566
ifXTable_rowreq_ctx *context;
2567
netsnmp_container *container;
2568
netsnmp_index index;
2571
if (strncmp(token, row_token, sizeof(row_token)) != 0) {
2572
snmp_log(LOG_ERR, "unknown token in _ifXTable_restore\n");
2576
container = _ifXTable_container_get();
2577
if (NULL == container) {
2578
snmp_log(LOG_ERR, "null container in _ifXTable_restore\n");
2582
DEBUGMSGTL(("ifXTable:restore", "parsing line '%s'\n", buf));
2585
* pull out index and find row
2588
buf = read_config_read_objid(buf, &index.oids, &index.len);
2591
"error reading row index in _ifXTable_restore\n");
2594
context = CONTAINER_FIND(container, &index);
2595
if (NULL == context) {
2597
"error finding row index in _ifXTable_restore\n");
2604
buf = skip_white(buf);
2605
if ((NULL == buf) || !isdigit(*buf)) {
2606
snmp_log(LOG_ERR, "unexpected format1 in _ifXTable_restore\n");
2611
* extract column, skip ':'
2613
col = (u_int) strtol(buf, &buf, 10);
2614
if ((NULL == buf) || (*buf != ':') || (COLUMN_IFALIAS != col)) {
2615
snmp_log(LOG_ERR, "unexpected format2 in _ifXTable_restore\n");
2623
DEBUGMSGTL(("ifXTable:restore", "parsing column %d\n", col));
2624
context->data.ifAlias_len = sizeof(context->data.ifAlias);
2625
buf = read_config_read_memory(ASN_OCTET_STR, buf,
2626
(char *) &context->data.ifAlias,
2627
(size_t *) &context->data.ifAlias_len);
2630
* extract column, skip ':'
2632
col = (u_int) strtol(buf, &buf, 10);
2633
if ((NULL == buf) || (*buf != ':') ||
2634
(COLUMN_IFLINKUPDOWNTRAPENABLE != col)) {
2635
snmp_log(LOG_ERR, "unexpected format3 in _ifXTable_restore\n");
2643
DEBUGMSGTL(("ifXTable:restore", "parsing column %d\n", col));
2644
len = sizeof(context->data.ifLinkUpDownTrapEnable);
2645
buf = read_config_read_memory(ASN_INTEGER, buf,
2646
(char *) &context->data.
2647
ifLinkUpDownTrapEnable, &len);
2650
* if the pointer is NULL and we didn't reach the
2651
* end of the line, something went wrong. Log message,
2652
* delete the row and bail.
2654
if ((buf == NULL) || (*buf != LINE_TERM_CHAR)) {
2655
snmp_log(LOG_ERR, "unexpected format4 in _ifXTable_restore\n");