1 /*
2  * Note: this file originally auto-generated by mib2c using
3  *       version : 1.48 $ of : mfd-top.m2c,v $
4  *
5  * $Id$
6  */
7 /** \page MFD helper for ipAddressTable
8  *
9  * \section intro Introduction
10  * Introductory text.
11  *
12  */
13 /*
14  * standard Net-SNMP includes
15  */
16 #include <net-snmp/net-snmp-config.h>
17 #include <net-snmp/net-snmp-features.h>
18 #include <net-snmp/net-snmp-includes.h>
19 #include <net-snmp/agent/net-snmp-agent-includes.h>
20 
21 #include <net-snmp/data_access/interface.h>
22 
23 /*
24  * include our parent header
25  */
26 #include "ipAddressTable.h"
27 
28 #include <net-snmp/agent/mib_modules.h>
29 
30 #include "ipAddressTable_interface.h"
31 
32 netsnmp_feature_require(check_storage_transition);
33 netsnmp_feature_require(ipaddress_entry_copy);
34 netsnmp_feature_require(ipaddress_prefix_copy);
35 
36 const oid       ipAddressTable_oid[] = { IPADDRESSTABLE_OID };
37 const int       ipAddressTable_oid_size = OID_LENGTH(ipAddressTable_oid);
38 
39 ipAddressTable_registration ipAddressTable_user_context;
40 static ipAddressTable_registration *ipAddressTable_user_context_p;
41 
42 void            initialize_table_ipAddressTable(void);
43 void            shutdown_table_ipAddressTable(void);
44 
45 
46 /* Called after the snmpd configuration has been read. */
47 static int
_init_ipAddressTable(int majorID,int minorID,void * serverargs,void * clientarg)48 _init_ipAddressTable(int majorID, int minorID, void *serverargs,
49                      void *clientarg)
50 {
51     DEBUGMSGTL(("verbose:ipAddressTable:init_ipAddressTable", "called\n"));
52 
53     netsnmp_access_interface_init();
54 
55     /*
56      * TODO:300:o: Perform ipAddressTable one-time module initialization.
57      */
58 
59     /*
60      * here we initialize all the tables we're planning on supporting
61      */
62     if (should_init("ipAddressTable"))
63         initialize_table_ipAddressTable();
64 
65     return 0;
66 }
67 
68 /**
69  * Initializes the ipAddressTable module
70  */
71 void
init_ipAddressTable(void)72 init_ipAddressTable(void)
73 {
74     snmp_register_callback(SNMP_CALLBACK_LIBRARY,
75                            SNMP_CALLBACK_POST_READ_CONFIG,
76                            _init_ipAddressTable, NULL);
77 }
78 
79 /**
80  * Shut-down the ipAddressTable module (agent is exiting)
81  */
82 void
shutdown_ipAddressTable(void)83 shutdown_ipAddressTable(void)
84 {
85     if (should_init("ipAddressTable"))
86         shutdown_table_ipAddressTable();
87 
88 }
89 
90 /**
91  * Initialize the table ipAddressTable
92  *    (Define its contents and how it's structured)
93  */
94 void
initialize_table_ipAddressTable(void)95 initialize_table_ipAddressTable(void)
96 {
97     u_long          flags;
98 
99     DEBUGMSGTL(("verbose:ipAddressTable:initialize_table_ipAddressTable",
100                 "called\n"));
101 
102     /*
103      * TODO:301:o: Perform ipAddressTable one-time table initialization.
104      */
105 
106     /*
107      * TODO:302:o: |->Initialize ipAddressTable user context
108      * if you'd like to pass in a pointer to some data for this
109      * table, allocate or set it up here.
110      */
111     ipAddressTable_user_context_p = NULL;
112 
113     /*
114      * No support for any flags yet, but in the future you would
115      * set any flags here.
116      */
117     flags = 0;
118 
119     /*
120      * call interface initialization code
121      */
122     _ipAddressTable_initialize_interface(ipAddressTable_user_context_p, flags);
123 }                               /* initialize_table_ipAddressTable */
124 
125 /**
126  * Shutdown the table ipAddressTable
127  */
128 void
shutdown_table_ipAddressTable(void)129 shutdown_table_ipAddressTable(void)
130 {
131     /*
132      * call interface shutdown code
133      */
134     _ipAddressTable_shutdown_interface(ipAddressTable_user_context_p);
135     netsnmp_free_all_list_data(ipAddressTable_user_context_p);
136     ipAddressTable_user_context_p = NULL;
137 }
138 
139 /**
140  * extra context initialization (eg default values)
141  *
142  * @param rowreq_ctx    : row request context
143  * @param user_init_ctx : void pointer for user (parameter to rowreq_ctx_allocate)
144  *
145  * @retval MFD_SUCCESS  : no errors
146  * @retval MFD_ERROR    : error (context allocate will fail)
147  */
148 int
ipAddressTable_rowreq_ctx_init(ipAddressTable_rowreq_ctx * rowreq_ctx,void * user_init_ctx)149 ipAddressTable_rowreq_ctx_init(ipAddressTable_rowreq_ctx * rowreq_ctx,
150                                void *user_init_ctx)
151 {
152     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_rowreq_ctx_init",
153                 "called\n"));
154 
155     netsnmp_assert(NULL != rowreq_ctx);
156 
157     /*
158      * TODO:210:o: |-> Perform extra ipAddressTable rowreq initialization. (eg DEFVALS)
159      */
160 
161     return MFD_SUCCESS;
162 }                               /* ipAddressTable_rowreq_ctx_init */
163 
164 /**
165  * extra context cleanup
166  *
167  */
168 void
ipAddressTable_rowreq_ctx_cleanup(ipAddressTable_rowreq_ctx * rowreq_ctx)169 ipAddressTable_rowreq_ctx_cleanup(ipAddressTable_rowreq_ctx * rowreq_ctx)
170 {
171     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_rowreq_ctx_cleanup",
172                 "called\n"));
173 
174     netsnmp_assert(NULL != rowreq_ctx);
175 
176     /*
177      * TODO:211:o: |-> Perform extra ipAddressTable rowreq cleanup.
178      */
179     if (NULL != rowreq_ctx->data) {
180         ipAddressTable_release_data(rowreq_ctx->data);
181         rowreq_ctx->data = NULL;
182     }
183 }                               /* ipAddressTable_rowreq_ctx_cleanup */
184 
185 /**
186  * pre-request callback
187  *
188  * @param user_context
189  *
190  * @retval MFD_SUCCESS              : success.
191  * @retval MFD_ERROR                : other error
192  */
193 int
ipAddressTable_pre_request(ipAddressTable_registration * user_context)194 ipAddressTable_pre_request(ipAddressTable_registration * user_context)
195 {
196     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_pre_request",
197                 "called\n"));
198 
199     /*
200      * TODO:510:o: Perform ipAddressTable pre-request actions.
201      */
202 
203     return MFD_SUCCESS;
204 }                               /* ipAddressTable_pre_request */
205 
206 /**
207  * post-request callback
208  *
209  * Note:
210  *   New rows have been inserted into the container, and
211  *   deleted rows have been removed from the container and
212  *   released.
213  *
214  * @param user_context
215  * @param rc : MFD_SUCCESS if all requests succeeded
216  *
217  * @retval MFD_SUCCESS : success.
218  * @retval MFD_ERROR   : other error (ignored)
219  */
220 int
ipAddressTable_post_request(ipAddressTable_registration * user_context,int rc)221 ipAddressTable_post_request(ipAddressTable_registration * user_context,
222                             int rc)
223 {
224     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_post_request",
225                 "called\n"));
226 
227     /*
228      * TODO:511:o: Perform ipAddressTable post-request actions.
229      */
230 
231     /*
232      * check to set if any rows were changed.
233      */
234     if (ipAddressTable_dirty_get()) {
235         /*
236          * check if request was successful. If so, this would be
237          * a good place to save data to its persistent store.
238          */
239         if (MFD_SUCCESS == rc) {
240             /*
241              * save changed rows, if you haven't already
242              */
243         }
244 
245         ipAddressTable_dirty_set(0);    /* clear table dirty flag */
246     }
247 
248     return MFD_SUCCESS;
249 }                               /* ipAddressTable_post_request */
250 
251 
252 /**********************************************************************
253  **********************************************************************
254  ***
255  *** Table ipAddressTable
256  ***
257  **********************************************************************
258  **********************************************************************/
259 /*
260  * IP-MIB::ipAddressTable is subid 34 of ip.
261  * Its status is Current.
262  * OID: .1.3.6.1.2.1.4.34, length: 8
263  */
264 
265 /*
266  * ---------------------------------------------------------------------
267  * * TODO:200:r: Implement ipAddressTable data context functions.
268  */
269 /*
270  * ipAddressTable_allocate_data
271  *
272  * Purpose: create new ipAddressTable_data.
273  */
274 ipAddressTable_data *
ipAddressTable_allocate_data(void)275 ipAddressTable_allocate_data(void)
276 {
277     /*
278      * TODO:201:r: |-> allocate memory for the ipAddressTable data context.
279      */
280     ipAddressTable_data *rtn = netsnmp_access_ipaddress_entry_create();
281 
282     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_allocate_data",
283                 "called\n"));
284 
285     if (NULL == rtn) {
286         snmp_log(LOG_ERR, "unable to malloc memory for new "
287                  "ipAddressTable_data.\n");
288     }
289 
290     return rtn;
291 }                               /* ipAddressTable_allocate_data */
292 
293 /*
294  * ipAddressTable_release_data
295  *
296  * Purpose: release ipAddressTable data.
297  */
298 void
ipAddressTable_release_data(ipAddressTable_data * data)299 ipAddressTable_release_data(ipAddressTable_data * data)
300 {
301     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_release_data",
302                 "called\n"));
303 
304     /*
305      * TODO:202:r: |-> release memory for the ipAddressTable data context.
306      */
307     netsnmp_access_ipaddress_entry_free(data);
308 }                               /* ipAddressTable_release_data */
309 
310 
311 /*---------------------------------------------------------------------
312  * IP-MIB::ipAddressEntry.ipAddressAddrType
313  * ipAddressAddrType is subid 1 of ipAddressEntry.
314  * Its status is Current, and its access level is NoAccess.
315  * OID: .1.3.6.1.2.1.4.34.1.1
316  * Description:
317 The address type of ipAddressAddr.
318  *
319  * Attributes:
320  *   accessible 0     isscalar 0     enums  1      hasdefval 0
321  *   readable   0     iscolumn 1     ranges 0      hashint   0
322  *   settable   0
323  *
324  * Enum range: 5/8. Values:  unknown(0), ipv4(1), ipv6(2), ipv4z(3), ipv6z(4), dns(16)
325  *
326  * Its syntax is InetAddressType (based on perltype INTEGER)
327  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
328  *
329  *
330  *
331  * NOTE: NODE ipAddressAddrType IS NOT ACCESSIBLE
332  *
333  *
334  */
335 /**
336  * map a value from its original native format to the MIB format.
337  *
338  * @retval MFD_SUCCESS         : success
339  * @retval MFD_ERROR           : Any other error
340  *
341  * @note parameters follow the memset convention (dest, src).
342  *
343  * @note generation and use of this function can be turned off by re-running
344  * mib2c after adding the following line to the file
345  * default-node-ipAddressAddrType.m2d :
346  *   @verbatim $m2c_node_skip_mapping = 1@endverbatim
347  *
348  * @remark
349  *  If the values for your data type don't exactly match the
350  *  possible values defined by the mib, you should map them here.
351  *  Otherwise, just do a direct copy.
352  */
353 int
ipAddressAddrType_map(long * mib_ipAddressAddrType_val_ptr,long raw_ipAddressAddrType_val)354 ipAddressAddrType_map(long * mib_ipAddressAddrType_val_ptr,
355                       long raw_ipAddressAddrType_val)
356 {
357     netsnmp_assert(NULL != mib_ipAddressAddrType_val_ptr);
358 
359     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressAddrType_map",
360                 "called\n"));
361 
362     /*
363      * TODO:241:o: |-> Implement ipAddressAddrType enum mapping.
364      * uses INTERNAL_* macros defined in the header files
365      */
366     switch (raw_ipAddressAddrType_val) {
367     case INTERNAL_IPADDRESSTABLE_IPADDRESSADDRTYPE_IPV4:
368         *mib_ipAddressAddrType_val_ptr = INETADDRESSTYPE_IPV4;
369         break;
370 
371     case INTERNAL_IPADDRESSTABLE_IPADDRESSADDRTYPE_IPV6:
372         *mib_ipAddressAddrType_val_ptr = INETADDRESSTYPE_IPV6;
373         break;
374 
375     default:
376         snmp_log(LOG_ERR, "couldn't map value %ld for ipAddressAddrType\n",
377                  raw_ipAddressAddrType_val);
378         *mib_ipAddressAddrType_val_ptr = INETADDRESSTYPE_UNKNOWN;
379     }
380 
381     return MFD_SUCCESS;
382 }                               /* ipAddressAddrType_map */
383 
384 
385 /**
386  * set mib index(es)
387  *
388  * @param tbl_idx mib index structure
389  * @param ipAddressAddrType_val
390  * @param ipAddressAddr_val_ptr
391  * @param ipAddressAddr_val_ptr_len
392  *
393  * @retval MFD_SUCCESS     : success.
394  * @retval MFD_ERROR       : other error.
395  *
396  * @remark
397  *  This convenience function is useful for setting all the MIB index
398  *  components with a single function call. It is assume that the C values
399  *  have already been mapped from their native/rawformat to the MIB format.
400  */
401 int
ipAddressTable_indexes_set_tbl_idx(ipAddressTable_mib_index * tbl_idx,long ipAddressAddrType_val,u_char * ipAddressAddr_val_ptr,size_t ipAddressAddr_val_ptr_len)402 ipAddressTable_indexes_set_tbl_idx(ipAddressTable_mib_index * tbl_idx,
403                                    long ipAddressAddrType_val,
404                                    u_char *ipAddressAddr_val_ptr,
405                                    size_t ipAddressAddr_val_ptr_len)
406 {
407     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_indexes_set_tbl_idx", "called\n"));
408 
409     /*
410      * ipAddressAddrType(1)/InetAddressType/ASN_INTEGER/long(u_long)//l/a/w/E/r/d/h
411      */
412     /** WARNING: this code might not work for netsnmp_ipaddress_entry */
413     ipAddressAddrType_map(&tbl_idx->ipAddressAddrType,
414                           ipAddressAddrType_val);
415 
416     /*
417      * ipAddressAddr(2)/InetAddress/ASN_OCTET_STR/char(char)//L/a/w/e/R/d/h
418      */
419     tbl_idx->ipAddressAddr_len = sizeof(tbl_idx->ipAddressAddr) / sizeof(tbl_idx->ipAddressAddr[0]);    /* max length */
420     /** WARNING: this code might not work for netsnmp_ipaddress_entry */
421     /*
422      * make sure there is enough space for ipAddressAddr data
423      */
424     if (tbl_idx->ipAddressAddr_len < ipAddressAddr_val_ptr_len) {
425         snmp_log(LOG_ERR, "not enough space for value\n");
426         return MFD_ERROR;
427     }
428     tbl_idx->ipAddressAddr_len = ipAddressAddr_val_ptr_len;
429     memcpy(tbl_idx->ipAddressAddr, ipAddressAddr_val_ptr,
430            ipAddressAddr_val_ptr_len * sizeof(ipAddressAddr_val_ptr[0]));
431 
432 
433     return MFD_SUCCESS;
434 }                               /* ipAddressTable_indexes_set_tbl_idx */
435 
436 /**
437  * @internal
438  * set row context indexes
439  *
440  * @param reqreq_ctx the row context that needs updated indexes
441  *
442  * @retval MFD_SUCCESS     : success.
443  * @retval MFD_ERROR       : other error.
444  *
445  * @remark
446  *  This function sets the mib indexs, then updates the oid indexs
447  *  from the mib index.
448  */
449 int
ipAddressTable_indexes_set(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressAddrType_val,u_char * ipAddressAddr_val_ptr,size_t ipAddressAddr_val_ptr_len)450 ipAddressTable_indexes_set(ipAddressTable_rowreq_ctx * rowreq_ctx,
451                            u_long ipAddressAddrType_val,
452                            u_char *ipAddressAddr_val_ptr,
453                            size_t ipAddressAddr_val_ptr_len)
454 {
455     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_indexes_set",
456                 "called\n"));
457 
458     if (MFD_SUCCESS !=
459         ipAddressTable_indexes_set_tbl_idx(&rowreq_ctx->tbl_idx,
460                                            ipAddressAddrType_val,
461                                            ipAddressAddr_val_ptr,
462                                            ipAddressAddr_val_ptr_len))
463         return MFD_ERROR;
464 
465     /*
466      * convert mib index to oid index
467      */
468     rowreq_ctx->oid_idx.len = sizeof(rowreq_ctx->oid_tmp) / sizeof(oid);
469     if (0 != ipAddressTable_index_to_oid(&rowreq_ctx->oid_idx,
470                                          &rowreq_ctx->tbl_idx)) {
471         return MFD_ERROR;
472     }
473 
474     return MFD_SUCCESS;
475 }                               /* ipAddressTable_indexes_set */
476 
477 
478 /*---------------------------------------------------------------------
479  * IP-MIB::ipAddressEntry.ipAddressIfIndex
480  * ipAddressIfIndex is subid 3 of ipAddressEntry.
481  * Its status is Current, and its access level is Create.
482  * OID: .1.3.6.1.2.1.4.34.1.3
483  * Description:
484 The index value which uniquely identifies the interface to
485             which this entry is applicable.  The interface identified by
486             a particular value of this index is the same interface as
487             identified by the same value of the IF-MIB's ifIndex.
488  *
489  * Attributes:
490  *   accessible 1     isscalar 0     enums  0      hasdefval 0
491  *   readable   1     iscolumn 1     ranges 1      hashint   1
492  *   settable   1
493  *   hint: d
494  *
495  * Ranges:  1 - 2147483647;
496  *
497  * Its syntax is InterfaceIndex (based on perltype INTEGER32)
498  * The net-snmp type is ASN_INTEGER. The C type decl is long (long)
499  */
500 /**
501  * Extract the current value of the ipAddressIfIndex data.
502  *
503  * Set a value using the data context for the row.
504  *
505  * @param rowreq_ctx
506  *        Pointer to the row request context.
507  * @param ipAddressIfIndex_val_ptr
508  *        Pointer to storage for a long variable
509  *
510  * @retval MFD_SUCCESS         : success
511  * @retval MFD_SKIP            : skip this node (no value for now)
512  * @retval MFD_ERROR           : Any other error
513  */
514 int
ipAddressIfIndex_get(ipAddressTable_rowreq_ctx * rowreq_ctx,long * ipAddressIfIndex_val_ptr)515 ipAddressIfIndex_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
516                      long *ipAddressIfIndex_val_ptr)
517 {
518    /** we should have a non-NULL pointer */
519     netsnmp_assert(NULL != ipAddressIfIndex_val_ptr);
520 
521 
522     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressIfIndex_get",
523                 "called\n"));
524 
525     netsnmp_assert(NULL != rowreq_ctx);
526 
527     /*
528      * TODO:231:o: |-> Extract the current value of the ipAddressIfIndex data.
529      * copy (* ipAddressIfIndex_val_ptr ) from rowreq_ctx->data
530      */
531     (*ipAddressIfIndex_val_ptr) = rowreq_ctx->data->if_index;
532 
533     return MFD_SUCCESS;
534 }                               /* ipAddressIfIndex_get */
535 
536 /*---------------------------------------------------------------------
537  * IP-MIB::ipAddressEntry.ipAddressType
538  * ipAddressType is subid 4 of ipAddressEntry.
539  * Its status is Current, and its access level is Create.
540  * OID: .1.3.6.1.2.1.4.34.1.4
541  * Description:
542 The type of address.  broadcast(3) is not a valid value for
543             IPv6 addresses (RFC3513).
544  *
545  * Attributes:
546  *   accessible 1     isscalar 0     enums  1      hasdefval 1
547  *   readable   1     iscolumn 1     ranges 0      hashint   0
548  *   settable   1
549  *   defval: unicast
550  *
551  * Enum range: 2/8. Values:  unicast(1), anycast(2), broadcast(3)
552  *
553  * Its syntax is INTEGER (based on perltype INTEGER)
554  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
555  */
556 /**
557  * Extract the current value of the ipAddressType data.
558  *
559  * Set a value using the data context for the row.
560  *
561  * @param rowreq_ctx
562  *        Pointer to the row request context.
563  * @param ipAddressType_val_ptr
564  *        Pointer to storage for a long variable
565  *
566  * @retval MFD_SUCCESS         : success
567  * @retval MFD_SKIP            : skip this node (no value for now)
568  * @retval MFD_ERROR           : Any other error
569  */
570 int
ipAddressType_get(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long * ipAddressType_val_ptr)571 ipAddressType_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
572                   u_long * ipAddressType_val_ptr)
573 {
574    /** we should have a non-NULL pointer */
575     netsnmp_assert(NULL != ipAddressType_val_ptr);
576 
577 
578     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressType_get", "called\n"));
579 
580     netsnmp_assert(NULL != rowreq_ctx);
581 
582     /*
583      * TODO:231:o: |-> Extract the current value of the ipAddressType data.
584      * copy (* ipAddressType_val_ptr ) from rowreq_ctx->data
585      */
586     (*ipAddressType_val_ptr) = rowreq_ctx->data->ia_type;
587 
588     return MFD_SUCCESS;
589 }                               /* ipAddressType_get */
590 
591 /*---------------------------------------------------------------------
592  * IP-MIB::ipAddressEntry.ipAddressPrefix
593  * ipAddressPrefix is subid 5 of ipAddressEntry.
594  * Its status is Current, and its access level is ReadOnly.
595  * OID: .1.3.6.1.2.1.4.34.1.5
596  * Description:
597 A pointer to the row in the prefix table to which this
598             address belongs.  May be { 0 0 } if there is no such row.
599  *
600  * Attributes:
601  *   accessible 1     isscalar 0     enums  0      hasdefval 1
602  *   readable   1     iscolumn 1     ranges 0      hashint   0
603  *   settable   0
604  *   defval: zeroDotZero
605  *
606  *
607  * Its syntax is RowPointer (based on perltype OBJECTID)
608  * The net-snmp type is ASN_OBJECT_ID. The C type decl is oid (oid)
609  * This data type requires a length.
610  */
611 /**
612  * Extract the current value of the ipAddressPrefix data.
613  *
614  * Set a value using the data context for the row.
615  *
616  * @param rowreq_ctx
617  *        Pointer to the row request context.
618  * @param ipAddressPrefix_val_ptr_ptr
619  *        Pointer to storage for a oid variable
620  * @param ipAddressPrefix_val_ptr_len_ptr
621  *        Pointer to a size_t. On entry, it will contain the size (in bytes)
622  *        pointed to by ipAddressPrefix.
623  *        On exit, this value should contain the data size (in bytes).
624  *
625  * @retval MFD_SUCCESS         : success
626  * @retval MFD_SKIP            : skip this node (no value for now)
627  * @retval MFD_ERROR           : Any other error
628 *
629  * @note If you need more than (*ipAddressPrefix_val_ptr_len_ptr) bytes of memory,
630  *       allocate it using malloc() and update ipAddressPrefix_val_ptr_ptr.
631  *       <b>DO NOT</b> free the previous pointer.
632  *       The MFD helper will release the memory you allocate.
633  *
634  * @remark If you call this function yourself, you are responsible
635  *         for checking if the pointer changed, and freeing any
636  *         previously allocated memory. (Not necessary if you pass
637  *         in a pointer to static memory, obviously.)
638  */
639 int
ipAddressPrefix_get(ipAddressTable_rowreq_ctx * rowreq_ctx,oid ** ipAddressPrefix_val_ptr_ptr,size_t * ipAddressPrefix_val_ptr_len_ptr)640 ipAddressPrefix_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
641                     oid ** ipAddressPrefix_val_ptr_ptr,
642                     size_t * ipAddressPrefix_val_ptr_len_ptr)
643 {
644     oid            *dst, tmp_oid[MAX_OID_LEN] =
645         { 1, 3, 6, 1, 2, 1, 4, 32, 1, 5 };
646     u_char          tmp_buf[NETSNMP_ACCESS_IPADDRESS_BUF_SIZE];
647     size_t          len;
648 
649    /** we should have a non-NULL pointer and enough storage */
650     netsnmp_assert((NULL != ipAddressPrefix_val_ptr_ptr)
651                    && (NULL != *ipAddressPrefix_val_ptr_ptr));
652     netsnmp_assert(NULL != ipAddressPrefix_val_ptr_len_ptr);
653 
654 
655     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressPrefix_get", "called\n"));
656 
657     netsnmp_assert(NULL != rowreq_ctx);
658 
659     /*
660      * TODO:231:o: |-> Extract the current value of the ipAddressPrefix data.
661      * copy (* ipAddressPrefix_val_ptr_ptr ) data and (* ipAddressPrefix_val_ptr_len_ptr ) from rowreq_ctx->data
662      */
663     dst = &tmp_oid[10];
664     *(dst++) = rowreq_ctx->data->if_index;
665     *(dst++) = rowreq_ctx->tbl_idx.ipAddressAddrType;
666     *(dst++) = rowreq_ctx->data->ia_address_len;
667     netsnmp_ipaddress_prefix_copy(tmp_buf,
668                                   (u_char *) rowreq_ctx->tbl_idx.ipAddressAddr,
669                                   rowreq_ctx->data->ia_address_len,
670                                   rowreq_ctx->data->ia_prefix_len);
671     for (len = 0; len < rowreq_ctx->data->ia_address_len; ++len)
672         *(dst++) = tmp_buf[len];
673     *(dst++) = rowreq_ctx->data->ia_prefix_len;
674     len = dst - tmp_oid;
675 
676     len *= sizeof((*ipAddressPrefix_val_ptr_ptr)[0]);
677     if ((*ipAddressPrefix_val_ptr_len_ptr) < len) {
678         (*ipAddressPrefix_val_ptr_ptr) = (oid*)malloc(len);
679         if (NULL == (*ipAddressPrefix_val_ptr_ptr)) {
680             snmp_log(LOG_ERR, "could not allocate memory\n");
681             return MFD_ERROR;
682         }
683     }
684     (*ipAddressPrefix_val_ptr_len_ptr) = len;
685     memcpy((*ipAddressPrefix_val_ptr_ptr), tmp_oid, len);
686 
687     return MFD_SUCCESS;
688 }                               /* ipAddressPrefix_get */
689 
690 /*---------------------------------------------------------------------
691  * IP-MIB::ipAddressEntry.ipAddressOrigin
692  * ipAddressOrigin is subid 6 of ipAddressEntry.
693  * Its status is Current, and its access level is ReadOnly.
694  * OID: .1.3.6.1.2.1.4.34.1.6
695  * Description:
696 The origin of the address.
697  *
698  * Attributes:
699  *   accessible 1     isscalar 0     enums  1      hasdefval 0
700  *   readable   1     iscolumn 1     ranges 0      hashint   0
701  *   settable   0
702  *
703  * Enum range: 4/8. Values:  other(1), manual(2), dhcp(4), linklayer(5), random(6)
704  *
705  * Its syntax is IpAddressOriginTC (based on perltype INTEGER)
706  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
707  */
708 /**
709  * Extract the current value of the ipAddressOrigin data.
710  *
711  * Set a value using the data context for the row.
712  *
713  * @param rowreq_ctx
714  *        Pointer to the row request context.
715  * @param ipAddressOrigin_val_ptr
716  *        Pointer to storage for a long variable
717  *
718  * @retval MFD_SUCCESS         : success
719  * @retval MFD_SKIP            : skip this node (no value for now)
720  * @retval MFD_ERROR           : Any other error
721  */
722 int
ipAddressOrigin_get(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long * ipAddressOrigin_val_ptr)723 ipAddressOrigin_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
724                     u_long * ipAddressOrigin_val_ptr)
725 {
726    /** we should have a non-NULL pointer */
727     netsnmp_assert(NULL != ipAddressOrigin_val_ptr);
728 
729 
730     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressOrigin_get", "called\n"));
731 
732     netsnmp_assert(NULL != rowreq_ctx);
733 
734     /*
735      * TODO:231:o: |-> Extract the current value of the ipAddressOrigin data.
736      * copy (* ipAddressOrigin_val_ptr ) from rowreq_ctx->data
737      */
738     (*ipAddressOrigin_val_ptr) = rowreq_ctx->data->ia_origin;
739 
740     return MFD_SUCCESS;
741 }                               /* ipAddressOrigin_get */
742 
743 /*---------------------------------------------------------------------
744  * IP-MIB::ipAddressEntry.ipAddressStatus
745  * ipAddressStatus is subid 7 of ipAddressEntry.
746  * Its status is Current, and its access level is Create.
747  * OID: .1.3.6.1.2.1.4.34.1.7
748  * Description:
749 The status of the address, describing if the address can be
750             used for communication.
751 
752 
753             In the absence of other information, an IPv4 address is
754             always preferred(1).
755  *
756  * Attributes:
757  *   accessible 1     isscalar 0     enums  1      hasdefval 1
758  *   readable   1     iscolumn 1     ranges 0      hashint   0
759  *   settable   1
760  *   defval: preferred
761  *
762  * Enum range: 5/8. Values:  preferred(1), invalid(3), inaccessible(4), unknown(5), tentative(6), duplicate(7)
763  *
764  * Its syntax is IpAddressStatusTC (based on perltype INTEGER)
765  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
766  */
767 /**
768  * Extract the current value of the ipAddressStatus data.
769  *
770  * Set a value using the data context for the row.
771  *
772  * @param rowreq_ctx
773  *        Pointer to the row request context.
774  * @param ipAddressStatus_val_ptr
775  *        Pointer to storage for a long variable
776  *
777  * @retval MFD_SUCCESS         : success
778  * @retval MFD_SKIP            : skip this node (no value for now)
779  * @retval MFD_ERROR           : Any other error
780  */
781 int
ipAddressStatus_get(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long * ipAddressStatus_val_ptr)782 ipAddressStatus_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
783                     u_long * ipAddressStatus_val_ptr)
784 {
785    /** we should have a non-NULL pointer */
786     netsnmp_assert(NULL != ipAddressStatus_val_ptr);
787 
788 
789     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStatus_get", "called\n"));
790 
791     netsnmp_assert(NULL != rowreq_ctx);
792 
793     /*
794      * TODO:231:o: |-> Extract the current value of the ipAddressStatus data.
795      * copy (* ipAddressStatus_val_ptr ) from rowreq_ctx->data
796      */
797     (*ipAddressStatus_val_ptr) = rowreq_ctx->data->ia_status;
798 
799     return MFD_SUCCESS;
800 }                               /* ipAddressStatus_get */
801 
802 /*---------------------------------------------------------------------
803  * IP-MIB::ipAddressEntry.ipAddressCreated
804  * ipAddressCreated is subid 8 of ipAddressEntry.
805  * Its status is Current, and its access level is ReadOnly.
806  * OID: .1.3.6.1.2.1.4.34.1.8
807  * Description:
808 The value of sysUpTime at the time this entry was created.
809             If this entry was created prior to the last re-
810             initialization of the local network management subsystem,
811             then this object contains a zero value.
812  *
813  * Attributes:
814  *   accessible 1     isscalar 0     enums  0      hasdefval 0
815  *   readable   1     iscolumn 1     ranges 0      hashint   0
816  *   settable   0
817  *
818  *
819  * Its syntax is TimeStamp (based on perltype TICKS)
820  * The net-snmp type is ASN_TIMETICKS. The C type decl is u_long (u_long)
821  */
822 /**
823  * Extract the current value of the ipAddressCreated data.
824  *
825  * Set a value using the data context for the row.
826  *
827  * @param rowreq_ctx
828  *        Pointer to the row request context.
829  * @param ipAddressCreated_val_ptr
830  *        Pointer to storage for a u_long variable
831  *
832  * @retval MFD_SUCCESS         : success
833  * @retval MFD_SKIP            : skip this node (no value for now)
834  * @retval MFD_ERROR           : Any other error
835  */
836 int
ipAddressCreated_get(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long * ipAddressCreated_val_ptr)837 ipAddressCreated_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
838                      u_long * ipAddressCreated_val_ptr)
839 {
840    /** we should have a non-NULL pointer */
841     netsnmp_assert(NULL != ipAddressCreated_val_ptr);
842 
843 
844     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressCreated_get",
845                 "called\n"));
846 
847     netsnmp_assert(NULL != rowreq_ctx);
848 
849     /*
850      * TODO:231:o: |-> Extract the current value of the ipAddressCreated data.
851      * copy (* ipAddressCreated_val_ptr ) from rowreq_ctx->data
852      */
853     (*ipAddressCreated_val_ptr) = rowreq_ctx->ipAddressCreated;
854 
855     return MFD_SUCCESS;
856 }                               /* ipAddressCreated_get */
857 
858 /*---------------------------------------------------------------------
859  * IP-MIB::ipAddressEntry.ipAddressLastChanged
860  * ipAddressLastChanged is subid 9 of ipAddressEntry.
861  * Its status is Current, and its access level is ReadOnly.
862  * OID: .1.3.6.1.2.1.4.34.1.9
863  * Description:
864 The value of sysUpTime at the time this entry was last
865             updated.  If this entry was updated prior to the last re-
866             initialization of the local network management subsystem,
867             then this object contains a zero value.
868  *
869  * Attributes:
870  *   accessible 1     isscalar 0     enums  0      hasdefval 0
871  *   readable   1     iscolumn 1     ranges 0      hashint   0
872  *   settable   0
873  *
874  *
875  * Its syntax is TimeStamp (based on perltype TICKS)
876  * The net-snmp type is ASN_TIMETICKS. The C type decl is u_long (u_long)
877  */
878 /**
879  * Extract the current value of the ipAddressLastChanged data.
880  *
881  * Set a value using the data context for the row.
882  *
883  * @param rowreq_ctx
884  *        Pointer to the row request context.
885  * @param ipAddressLastChanged_val_ptr
886  *        Pointer to storage for a u_long variable
887  *
888  * @retval MFD_SUCCESS         : success
889  * @retval MFD_SKIP            : skip this node (no value for now)
890  * @retval MFD_ERROR           : Any other error
891  */
892 int
ipAddressLastChanged_get(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long * ipAddressLastChanged_val_ptr)893 ipAddressLastChanged_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
894                          u_long * ipAddressLastChanged_val_ptr)
895 {
896    /** we should have a non-NULL pointer */
897     netsnmp_assert(NULL != ipAddressLastChanged_val_ptr);
898 
899 
900     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressLastChanged_get",
901                 "called\n"));
902 
903     netsnmp_assert(NULL != rowreq_ctx);
904 
905     /*
906      * TODO:231:o: |-> Extract the current value of the ipAddressLastChanged data.
907      * copy (* ipAddressLastChanged_val_ptr ) from rowreq_ctx->data
908      */
909     (*ipAddressLastChanged_val_ptr) = rowreq_ctx->ipAddressLastChanged;
910 
911     return MFD_SUCCESS;
912 }                               /* ipAddressLastChanged_get */
913 
914 /*---------------------------------------------------------------------
915  * IP-MIB::ipAddressEntry.ipAddressRowStatus
916  * ipAddressRowStatus is subid 10 of ipAddressEntry.
917  * Its status is Current, and its access level is Create.
918  * OID: .1.3.6.1.2.1.4.34.1.10
919  * Description:
920 The status of this conceptual row.
921 
922 
923             The RowStatus TC requires that this DESCRIPTION clause
924             states under which circumstances other objects in this row
925             can be modified.  The value of this object has no effect on
926             whether other objects in this conceptual row can be
927             modified.
928 
929 
930             A conceptual row can not be made active until the
931             ipAddressIfIndex has been set to a valid index.
932  *
933  * Attributes:
934  *   accessible 1     isscalar 0     enums  1      hasdefval 0
935  *   readable   1     iscolumn 1     ranges 0      hashint   0
936  *   settable   1
937  *
938  * Enum range: 3/8. Values:  active(1), notInService(2), notReady(3), createAndGo(4), createAndWait(5), destroy(6)
939  *
940  * Its syntax is RowStatus (based on perltype INTEGER)
941  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
942  */
943 /**
944  * Extract the current value of the ipAddressRowStatus data.
945  *
946  * Set a value using the data context for the row.
947  *
948  * @param rowreq_ctx
949  *        Pointer to the row request context.
950  * @param ipAddressRowStatus_val_ptr
951  *        Pointer to storage for a long variable
952  *
953  * @retval MFD_SUCCESS         : success
954  * @retval MFD_SKIP            : skip this node (no value for now)
955  * @retval MFD_ERROR           : Any other error
956  */
957 int
ipAddressRowStatus_get(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long * ipAddressRowStatus_val_ptr)958 ipAddressRowStatus_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
959                        u_long * ipAddressRowStatus_val_ptr)
960 {
961    /** we should have a non-NULL pointer */
962     netsnmp_assert(NULL != ipAddressRowStatus_val_ptr);
963 
964     /** WARNING: this code might not work for netsnmp_ipaddress_entry */
965     if(rowreq_ctx->data->if_index)
966        (*ipAddressRowStatus_val_ptr) = rowreq_ctx->ipAddressRowStatus;
967     else
968        (*ipAddressRowStatus_val_ptr) = ROWSTATUS_NOTREADY;
969 
970     return MFD_SUCCESS;
971 }                               /* ipAddressRowStatus_get */
972 
973 /*---------------------------------------------------------------------
974  * IP-MIB::ipAddressEntry.ipAddressStorageType
975  * ipAddressStorageType is subid 11 of ipAddressEntry.
976  * Its status is Current, and its access level is Create.
977  * OID: .1.3.6.1.2.1.4.34.1.11
978  * Description:
979 The storage type for this conceptual row.  If this object
980             has a value of 'permanent' then no other objects are
981             required to be able to be modified.
982  *
983  * Attributes:
984  *   accessible 1     isscalar 0     enums  1      hasdefval 1
985  *   readable   1     iscolumn 1     ranges 0      hashint   0
986  *   settable   1
987  *   defval: volatile
988  *
989  * Enum range: 4/8. Values:  other(1), volatile(2), nonVolatile(3), permanent(4), readOnly(5)
990  *
991  * Its syntax is StorageType (based on perltype INTEGER)
992  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
993  */
994 /**
995  * Extract the current value of the ipAddressStorageType data.
996  *
997  * Set a value using the data context for the row.
998  *
999  * @param rowreq_ctx
1000  *        Pointer to the row request context.
1001  * @param ipAddressStorageType_val_ptr
1002  *        Pointer to storage for a long variable
1003  *
1004  * @retval MFD_SUCCESS         : success
1005  * @retval MFD_SKIP            : skip this node (no value for now)
1006  * @retval MFD_ERROR           : Any other error
1007  */
1008 int
ipAddressStorageType_get(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long * ipAddressStorageType_val_ptr)1009 ipAddressStorageType_get(ipAddressTable_rowreq_ctx * rowreq_ctx,
1010                          u_long * ipAddressStorageType_val_ptr)
1011 {
1012    /** we should have a non-NULL pointer */
1013     netsnmp_assert(NULL != ipAddressStorageType_val_ptr);
1014 
1015 
1016     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStorageType_get",
1017                 "called\n"));
1018 
1019     netsnmp_assert(NULL != rowreq_ctx);
1020 
1021     /*
1022      * TODO:231:o: |-> Extract the current value of the ipAddressStorageType data.
1023      * copy (* ipAddressStorageType_val_ptr ) from rowreq_ctx->data
1024      */
1025     (*ipAddressStorageType_val_ptr) = rowreq_ctx->data->ia_storagetype;
1026 
1027     return MFD_SUCCESS;
1028 }                               /* ipAddressStorageType_get */
1029 
1030 
1031 
1032 /** @} */
1033 /**********************************************************************
1034  **********************************************************************
1035  ***
1036  *** Table ipAddressTable
1037  ***
1038  **********************************************************************
1039  **********************************************************************/
1040 /*
1041  * IP-MIB::ipAddressTable is subid 34 of ip.
1042  * Its status is Current.
1043  * OID: .1.3.6.1.2.1.4.34, length: 8
1044  */
1045     /*
1046      * NOTE: if you update this chart, please update the versions in
1047      *       local/mib2c-conf.d/parent-set.m2i
1048      *       agent/mibgroup/helpers/baby_steps.c
1049      * while you're at it.
1050      */
1051     /*
1052      ***********************************************************************
1053      * Baby Steps Flow Chart (2004.06.05)                                  *
1054      *                                                                     *
1055      * +--------------+    +================+    U = unconditional path    *
1056      * |optional state|    ||required state||    S = path for success      *
1057      * +--------------+    +================+    E = path for error        *
1058      ***********************************************************************
1059      *
1060      *                        +--------------+
1061      *                        |     pre      |
1062      *                        |   request    |
1063      *                        +--------------+
1064      *                               | U
1065      * +-------------+        +==============+
1066      * |    row    |f|<-------||  object    ||
1067      * |  create   |1|      E ||  lookup    ||
1068      * +-------------+        +==============+
1069      *     E |   | S                 | S
1070      *       |   +------------------>|
1071      *       |                +==============+
1072      *       |              E ||   check    ||
1073      *       |<---------------||   values   ||
1074      *       |                +==============+
1075      *       |                       | S
1076      *       |                +==============+
1077      *       |       +<-------||   undo     ||
1078      *       |       |      E ||   setup    ||
1079      *       |       |        +==============+
1080      *       |       |               | S
1081      *       |       |        +==============+
1082      *       |       |        ||    set     ||-------------------------->+
1083      *       |       |        ||   value    || E                         |
1084      *       |       |        +==============+                           |
1085      *       |       |               | S                                 |
1086      *       |       |        +--------------+                           |
1087      *       |       |        |    check     |-------------------------->|
1088      *       |       |        |  consistency | E                         |
1089      *       |       |        +--------------+                           |
1090      *       |       |               | S                                 |
1091      *       |       |        +==============+         +==============+  |
1092      *       |       |        ||   commit   ||-------->||     undo   ||  |
1093      *       |       |        ||            || E       ||    commit  ||  |
1094      *       |       |        +==============+         +==============+  |
1095      *       |       |               | S                     U |<--------+
1096      *       |       |        +--------------+         +==============+
1097      *       |       |        | irreversible |         ||    undo    ||
1098      *       |       |        |    commit    |         ||     set    ||
1099      *       |       |        +--------------+         +==============+
1100      *       |       |               | U                     U |
1101      *       |       +-------------->|<------------------------+
1102      *       |                +==============+
1103      *       |                ||   undo     ||
1104      *       |                ||  cleanup   ||
1105      *       |                +==============+
1106      *       +---------------------->| U
1107      *                               |
1108      *                          (err && f1)------------------->+
1109      *                               |                         |
1110      *                        +--------------+         +--------------+
1111      *                        |    post      |<--------|      row     |
1112      *                        |   request    |       U |    release   |
1113      *                        +--------------+         +--------------+
1114      *
1115      */
1116 
1117 /**
1118  * Setup up context with information needed to undo a set request.
1119  *
1120  * This function will be called before the individual node undo setup
1121  * functions are called. If you need to do any undo setup that is not
1122  * related to a specific column, you can do it here.
1123  *
1124  * Note that the undo context has been allocated with
1125  * ipAddressTable_allocate_data(), but may need extra
1126  * initialization similar to what you may have done in
1127  * ipAddressTable_rowreq_ctx_init().
1128  * Note that an individual node's undo_setup function will only be called
1129  * if that node is being set to a new value.
1130  *
1131  * If there is any setup specific to a particular column (e.g. allocating
1132  * memory for a string), you should do that setup in the node's undo_setup
1133  * function, so it won't be done unless it is necessary.
1134  *
1135  * @param rowreq_ctx
1136  *        Pointer to the table context (ipAddressTable_rowreq_ctx)
1137  *
1138  * @retval MFD_SUCCESS : success
1139  * @retval MFD_ERROR   : error. set will fail.
1140  */
1141 int
ipAddressTable_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)1142 ipAddressTable_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)
1143 {
1144     int             rc = MFD_SUCCESS;
1145 
1146     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_undo_setup",
1147                 "called\n"));
1148 
1149     /** we should have a non-NULL pointer */
1150     netsnmp_assert(NULL != rowreq_ctx);
1151 
1152     /*
1153      * TODO:451:M: |-> Setup ipAddressTable undo.
1154      * set up ipAddressTable undo information, in preparation for a set.
1155      * Undo storage is in (* ipAddressStorageType_val_ptr )*
1156      */
1157     /*
1158      * check for storage types that don't allow modification.
1159      * probably should try and do this earlier (and we could, by
1160      * adding code to the interface file), but this ought to suffice.
1161      */
1162     if (STORAGETYPE_READONLY == rowreq_ctx->data->ia_storagetype) {
1163         DEBUGMSGTL(("ipAddressTable", "can't change readonly row\n"));
1164         return MFD_NOT_VALID_EVER;
1165     }
1166 
1167     /*
1168      * save last changed
1169      */
1170     rowreq_ctx->ipAddressLastChanged_undo =
1171         rowreq_ctx->ipAddressLastChanged;
1172 
1173 
1174     /*
1175      * just copy everything
1176      */
1177     rc = netsnmp_access_ipaddress_entry_copy(rowreq_ctx->undo,
1178                                              rowreq_ctx->data);
1179 
1180     return rc;
1181 }                               /* ipAddressTable_undo_setup */
1182 
1183 /**
1184  * Undo a set request.
1185  *
1186  * This function will be called before the individual node undo
1187  * functions are called. If you need to do any undo that is not
1188  * related to a specific column, you can do it here.
1189  *
1190  * Note that an individual node's undo function will only be called
1191  * if that node is being set to a new value.
1192  *
1193  * If there is anything  specific to a particular column (e.g. releasing
1194  * memory for a string), you should do that setup in the node's undo
1195  * function, so it won't be done unless it is necessary.
1196  *
1197  * @param rowreq_ctx
1198  *        Pointer to the table context (ipAddressTable_rowreq_ctx)
1199  *
1200  * @retval MFD_SUCCESS : success
1201  * @retval MFD_ERROR   : error. set will fail.
1202  */
1203 int
ipAddressTable_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)1204 ipAddressTable_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)
1205 {
1206     int             rc = MFD_SUCCESS;
1207 
1208     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_undo", "called\n"));
1209 
1210     /** we should have a non-NULL pointer */
1211     netsnmp_assert(NULL != rowreq_ctx);
1212 
1213     /*
1214      * TODO:451:M: |-> ipAddressTable undo.
1215      * ipAddressTable undo information, in response to a failed set.
1216      * Undo storage is in (* ipAddressStorageType_val_ptr )*
1217      */
1218 
1219     return rc;
1220 }                               /* ipAddressTable_undo_setup */
1221 
1222 /**
1223  * Cleanup up context undo information.
1224  *
1225  * This function will be called after set/commit processing. If you
1226  * allocated any resources in undo_setup, this is the place to release
1227  * those resources.
1228  *
1229  * This function is called regardless of the success or failure of the set
1230  * request. If you need to perform different steps for cleanup depending
1231  * on success or failure, you can add a flag to the rowreq_ctx.
1232  *
1233  * @param rowreq_ctx
1234  *        Pointer to the table context (ipAddressTable_rowreq_ctx)
1235  *
1236  * @retval MFD_SUCCESS : success
1237  * @retval MFD_ERROR   : error
1238  */
1239 int
ipAddressTable_undo_cleanup(ipAddressTable_rowreq_ctx * rowreq_ctx)1240 ipAddressTable_undo_cleanup(ipAddressTable_rowreq_ctx * rowreq_ctx)
1241 {
1242     int             rc = MFD_SUCCESS;
1243 
1244     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_undo_cleanup",
1245                 "called\n"));
1246 
1247     /** we should have a non-NULL pointer */
1248     netsnmp_assert(NULL != rowreq_ctx);
1249 
1250     /*
1251      * TODO:452:M: |-> Cleanup ipAddressTable undo.
1252      * Undo storage is in (* ipAddressStorageType_val_ptr )*
1253      */
1254     rowreq_ctx->ipAddressLastChanged =
1255         rowreq_ctx->ipAddressLastChanged_undo;
1256 
1257     return rc;
1258 }                               /* ipAddressTable_undo_cleanup */
1259 
1260 /**
1261  * commit new values.
1262  *
1263  * At this point, you should have done everything you can to ensure that
1264  * this commit will not fail.
1265  *
1266  * Should you need different behavior depending on which columns were
1267  * set, rowreq_ctx->column_set_flags will indicate which writeable columns were
1268  * set. The definitions for the COLUMN_*_FLAG bits can be found in
1269  * ipAddressTable.h.
1270  * A new row will have the MFD_ROW_CREATED bit set in rowreq_flags.
1271  *
1272  * @param rowreq_ctx
1273  *        Pointer to the users context.
1274  *
1275  * @retval MFD_SUCCESS : success
1276  * @retval MFD_ERROR   : error
1277  */
1278 int
ipAddressTable_commit(ipAddressTable_rowreq_ctx * rowreq_ctx)1279 ipAddressTable_commit(ipAddressTable_rowreq_ctx * rowreq_ctx)
1280 {
1281     int             rc = MFD_SUCCESS;
1282 
1283     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_commit",
1284                 "called\n"));
1285 
1286     /** we should have a non-NULL pointer */
1287     netsnmp_assert(NULL != rowreq_ctx);
1288 
1289     /*
1290      * commit ipAddressTable data
1291      * 1) check the column's flag to see if it was set.
1292      * 2) clear the flag when you handle that column
1293      * 3) set the column's flag in column_set_flags if it needs undo
1294      *    processing in case of a failure.
1295      */
1296     /*
1297      * did anything change?
1298      */
1299     if (0 == rowreq_ctx->column_set_flags) {
1300         DEBUGMSGTL(("ipAddressTable:ipAddressTable_commit",
1301                     "no change\n"));
1302         return MFD_SUCCESS;
1303     }
1304 
1305     /*
1306      * pass everything to data access
1307      * let data access know what columns are set
1308      */
1309     rowreq_ctx->data->flags = rowreq_ctx->column_set_flags;
1310 
1311     if (rowreq_ctx->column_set_flags & COLUMN_IPADDRESSROWSTATUS_FLAG) {
1312         if (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED) {
1313             rowreq_ctx->data->flags |= NETSNMP_ACCESS_IPADDRESS_CREATE;
1314             rowreq_ctx->ipAddressCreated = netsnmp_get_agent_uptime();
1315         } else if (ROWSTATUS_DESTROY == rowreq_ctx->ipAddressRowStatus) {
1316             rowreq_ctx->data->flags |= NETSNMP_ACCESS_IPADDRESS_DELETE;
1317         } else
1318             rowreq_ctx->data->flags |= NETSNMP_ACCESS_IPADDRESS_CHANGE;
1319     } else
1320         rowreq_ctx->data->flags |= NETSNMP_ACCESS_IPADDRESS_CHANGE;
1321 
1322     /*
1323      * do it
1324      */
1325     rc = netsnmp_access_ipaddress_entry_set(rowreq_ctx->data);
1326     if (rc) {
1327         DEBUGMSGTL(("ipAddressTable",
1328                     "bad rc %d from IP address data access\n", rc));
1329         rc = MFD_ERROR;
1330     } else {
1331         rowreq_ctx->ipAddressLastChanged = netsnmp_get_agent_uptime();
1332     }
1333 
1334     /*
1335      * if we successfully commited this row, set the dirty flag.
1336      */
1337     if (MFD_SUCCESS == rc) {
1338         rowreq_ctx->rowreq_flags |= MFD_ROW_DIRTY;
1339     }
1340 
1341     return rc;
1342 }                               /* ipAddressTable_commit */
1343 
1344 /**
1345  * undo commit new values.
1346  *
1347  * Should you need different behavior depending on which columns were
1348  * set, rowreq_ctx->column_set_flags will indicate which writeable columns were
1349  * set. The definitions for the COLUMN_*_FLAG bits can be found in
1350  * ipAddressTable.h.
1351  * A new row will have the MFD_ROW_CREATED bit set in rowreq_flags.
1352  *
1353  * @param rowreq_ctx
1354  *        Pointer to the users context.
1355  *
1356  * @retval MFD_SUCCESS : success
1357  * @retval MFD_ERROR   : error
1358  */
1359 int
ipAddressTable_undo_commit(ipAddressTable_rowreq_ctx * rowreq_ctx)1360 ipAddressTable_undo_commit(ipAddressTable_rowreq_ctx * rowreq_ctx)
1361 {
1362     int             rc = MFD_SUCCESS;
1363 
1364     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_undo_commit",
1365                 "called\n"));
1366 
1367     /** we should have a non-NULL pointer */
1368     netsnmp_assert(NULL != rowreq_ctx);
1369 
1370     /*
1371      * TODO:485:M: |-> Undo ipAddressTable commit.
1372      * check the column's flag in rowreq_ctx->column_set_flags to see
1373      * if it was set during commit, then undo it.
1374      *
1375      * eg: if (rowreq_ctx->column_set_flags & COLUMN__FLAG) {}
1376      */
1377     if (rowreq_ctx->column_set_flags & COLUMN_IPADDRESSROWSTATUS_FLAG) {
1378         /*
1379          * if we created an addr, delete it. if we deleted it,
1380          * re-create it. If we changed it, change it back.
1381          */
1382         if (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED) {
1383             rowreq_ctx->undo->flags |= NETSNMP_ACCESS_IPADDRESS_DELETE;
1384         } else if (ROWSTATUS_DESTROY == rowreq_ctx->ipAddressRowStatus) {
1385             rowreq_ctx->undo->flags |= NETSNMP_ACCESS_IPADDRESS_CREATE;
1386         } else
1387             rowreq_ctx->undo->flags |= NETSNMP_ACCESS_IPADDRESS_CHANGE;
1388     } else
1389         rowreq_ctx->undo->flags |= NETSNMP_ACCESS_IPADDRESS_CHANGE;
1390 
1391     /*
1392      * do it
1393      */
1394     rc = netsnmp_access_ipaddress_entry_set(rowreq_ctx->undo);
1395     if (rc) {
1396         DEBUGMSGTL(("ipAddressTable",
1397                     "bad rc %d from IP address data access\n", rc));
1398         rc = MFD_ERROR;
1399     }
1400 
1401     /*
1402      * if we successfully un-commited this row, clear the dirty flag.
1403      */
1404     if (MFD_SUCCESS == rc) {
1405         rowreq_ctx->rowreq_flags &= ~MFD_ROW_DIRTY;
1406     }
1407 
1408     return rc;
1409 }                               /* ipAddressTable_undo_commit */
1410 
1411 /*
1412  * TODO:440:M: Implement ipAddressTable node value checks.
1413  * TODO:450:M: Implement ipAddressTable undo functions.
1414  * TODO:460:M: Implement ipAddressTable set functions.
1415  * TODO:480:M: Implement ipAddressTable commit functions.
1416  */
1417 /*---------------------------------------------------------------------
1418  * IP-MIB::ipAddressEntry.ipAddressIfIndex
1419  * ipAddressIfIndex is subid 3 of ipAddressEntry.
1420  * Its status is Current, and its access level is Create.
1421  * OID: .1.3.6.1.2.1.4.34.1.3
1422  * Description:
1423 The index value which uniquely identifies the interface to
1424             which this entry is applicable.  The interface identified by
1425             a particular value of this index is the same interface as
1426             identified by the same value of the IF-MIB's ifIndex.
1427  *
1428  * Attributes:
1429  *   accessible 1     isscalar 0     enums  0      hasdefval 0
1430  *   readable   1     iscolumn 1     ranges 1      hashint   1
1431  *   settable   1
1432  *   hint: d
1433  *
1434  * Ranges:  1 - 2147483647;
1435  *
1436  * Its syntax is InterfaceIndex (based on perltype INTEGER32)
1437  * The net-snmp type is ASN_INTEGER. The C type decl is long (long)
1438  */
1439 /**
1440  * Check that the proposed new value is potentially valid.
1441  *
1442  * @param rowreq_ctx
1443  *        Pointer to the row request context.
1444  * @param ipAddressIfIndex_val
1445  *        A long containing the new value.
1446  *
1447  * @retval MFD_SUCCESS        : incoming value is legal
1448  * @retval MFD_NOT_VALID_NOW  : incoming value is not valid now
1449  * @retval MFD_NOT_VALID_EVER : incoming value is never valid
1450  *
1451  * This is the place to check for requirements that are not
1452  * expressed in the mib syntax (for example, a requirement that
1453  * is detailed in the description for an object).
1454  *
1455  * You should check that the requested change between the undo value and the
1456  * new value is legal (ie, the transistion from one value to another
1457  * is legal).
1458  *
1459  *@note
1460  * This check is only to determine if the new value
1461  * is \b potentially valid. This is the first check of many, and
1462  * is one of the simplest ones.
1463  *
1464  *@note
1465  * this is not the place to do any checks for values
1466  * which depend on some other value in the mib. Those
1467  * types of checks should be done in the
1468  * ipAddressTable_check_dependencies() function.
1469  *
1470  * The following checks have already been done for you:
1471  *    The syntax is ASN_INTEGER
1472  *    The value is in (one of) the range set(s):  1 - 2147483647
1473  *
1474  * If there a no other checks you need to do, simply return MFD_SUCCESS.
1475  *
1476  */
1477 int
ipAddressIfIndex_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,long ipAddressIfIndex_val)1478 ipAddressIfIndex_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,
1479                              long ipAddressIfIndex_val)
1480 {
1481     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressIfIndex_check_value",
1482                 "called\n"));
1483 
1484     /** should never get a NULL pointer */
1485     netsnmp_assert(NULL != rowreq_ctx);
1486 
1487     /*
1488      * TODO:441:o: |-> Check for valid ipAddressIfIndex value.
1489      */
1490     /*
1491      * if the new value is the same as the old, accept it.
1492      */
1493     if (ipAddressIfIndex_val == (long)rowreq_ctx->data->if_index)
1494         return MFD_SUCCESS;
1495 
1496     /*
1497      * currently don't support moving addresses between interfaces, so
1498      * if this isn't a new row, return error.
1499      */
1500     if (!(rowreq_ctx->rowreq_flags & MFD_ROW_CREATED)) {
1501         DEBUGMSGT(("ipAddressTable",
1502                    "changing ifIndex value not supported\n"));
1503         return MFD_NOT_VALID_EVER;
1504     }
1505 
1506     /*
1507      * find name for ifIndex
1508      */
1509     if (NULL == netsnmp_access_interface_name_find(ipAddressIfIndex_val)) {
1510         DEBUGMSGT(("ipAddressTable", "cant find name for index %ld\n",
1511                    ipAddressIfIndex_val));
1512         return MFD_NOT_VALID_NOW;
1513     }
1514 
1515     return MFD_SUCCESS;         /* ipAddressIfIndex value not illegal */
1516 }                               /* ipAddressIfIndex_check_value */
1517 
1518 /**
1519  * Save old value information
1520  *
1521  * @param rowreq_ctx
1522  *        Pointer to the table context (ipAddressTable_rowreq_ctx)
1523  *
1524  * @retval MFD_SUCCESS : success
1525  * @retval MFD_ERROR   : error. set will fail.
1526  *
1527  * This function will be called after the table level undo setup function
1528  * ipAddressTable_undo_setup has been called.
1529  *
1530  *@note
1531  * this function will only be called if a new value is set for this column.
1532  *
1533  * If there is any setup specific to a particular column (e.g. allocating
1534  * memory for a string), you should do that setup in this function, so it
1535  * won't be done unless it is necessary.
1536  */
1537 int
ipAddressIfIndex_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)1538 ipAddressIfIndex_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)
1539 {
1540     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressIfIndex_undo_setup",
1541                 "called\n"));
1542 
1543     /** should never get a NULL pointer */
1544     netsnmp_assert(NULL != rowreq_ctx);
1545 
1546     /*
1547      * TODO:455:o: |-> Setup ipAddressIfIndex undo.
1548      */
1549     /*
1550      * handled in ipAddressTable_undo_setup
1551      */
1552 
1553     return MFD_SUCCESS;
1554 }                               /* ipAddressIfIndex_undo_setup */
1555 
1556 /**
1557  * Set the new value.
1558  *
1559  * @param rowreq_ctx
1560  *        Pointer to the users context. You should know how to
1561  *        manipulate the value from this object.
1562  * @param ipAddressIfIndex_val
1563  *        A long containing the new value.
1564  */
1565 int
ipAddressIfIndex_set(ipAddressTable_rowreq_ctx * rowreq_ctx,long ipAddressIfIndex_val)1566 ipAddressIfIndex_set(ipAddressTable_rowreq_ctx * rowreq_ctx,
1567                      long ipAddressIfIndex_val)
1568 {
1569 
1570     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressIfIndex_set",
1571                 "called\n"));
1572 
1573     /** should never get a NULL pointer */
1574     netsnmp_assert(NULL != rowreq_ctx);
1575 
1576     /*
1577      * TODO:461:M: |-> Set ipAddressIfIndex value.
1578      * set ipAddressIfIndex value in rowreq_ctx->data
1579      */
1580     if (rowreq_ctx->data->if_index != (oid)ipAddressIfIndex_val)
1581         rowreq_ctx->data->if_index  = (oid)ipAddressIfIndex_val;
1582     else
1583         rowreq_ctx->column_set_flags &= ~COLUMN_IPADDRESSIFINDEX_FLAG;
1584 
1585     return MFD_SUCCESS;
1586 }                               /* ipAddressIfIndex_set */
1587 
1588 /**
1589  * undo the previous set.
1590  *
1591  * @param rowreq_ctx
1592  *        Pointer to the users context.
1593  */
1594 int
ipAddressIfIndex_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)1595 ipAddressIfIndex_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)
1596 {
1597 
1598     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressIfIndex_undo",
1599                 "called\n"));
1600 
1601     netsnmp_assert(NULL != rowreq_ctx);
1602 
1603     /*
1604      * TODO:456:o: |-> Clean up ipAddressIfIndex undo.
1605      */
1606     /*
1607      * copy ipAddressIfIndex data
1608      * set rowreq_ctx->data->ipAddressIfIndex from rowreq_ctx->undo->ipAddressIfIndex
1609      */
1610     rowreq_ctx->data->if_index = rowreq_ctx->undo->if_index;
1611 
1612     return MFD_SUCCESS;
1613 }                               /* ipAddressIfIndex_undo */
1614 
1615 /*---------------------------------------------------------------------
1616  * IP-MIB::ipAddressEntry.ipAddressType
1617  * ipAddressType is subid 4 of ipAddressEntry.
1618  * Its status is Current, and its access level is Create.
1619  * OID: .1.3.6.1.2.1.4.34.1.4
1620  * Description:
1621 The type of address.  broadcast(3) is not a valid value for
1622             IPv6 addresses (RFC3513).
1623  *
1624  * Attributes:
1625  *   accessible 1     isscalar 0     enums  1      hasdefval 1
1626  *   readable   1     iscolumn 1     ranges 0      hashint   0
1627  *   settable   1
1628  *   defval: unicast
1629  *
1630  * Enum range: 2/8. Values:  unicast(1), anycast(2), broadcast(3)
1631  *
1632  * Its syntax is INTEGER (based on perltype INTEGER)
1633  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
1634  */
1635 /**
1636  * Check that the proposed new value is potentially valid.
1637  *
1638  * @param rowreq_ctx
1639  *        Pointer to the row request context.
1640  * @param ipAddressType_val
1641  *        A long containing the new value.
1642  *
1643  * @retval MFD_SUCCESS        : incoming value is legal
1644  * @retval MFD_NOT_VALID_NOW  : incoming value is not valid now
1645  * @retval MFD_NOT_VALID_EVER : incoming value is never valid
1646  *
1647  * This is the place to check for requirements that are not
1648  * expressed in the mib syntax (for example, a requirement that
1649  * is detailed in the description for an object).
1650  *
1651  * You should check that the requested change between the undo value and the
1652  * new value is legal (ie, the transistion from one value to another
1653  * is legal).
1654  *
1655  *@note
1656  * This check is only to determine if the new value
1657  * is \b potentially valid. This is the first check of many, and
1658  * is one of the simplest ones.
1659  *
1660  *@note
1661  * this is not the place to do any checks for values
1662  * which depend on some other value in the mib. Those
1663  * types of checks should be done in the
1664  * ipAddressTable_check_dependencies() function.
1665  *
1666  * The following checks have already been done for you:
1667  *    The syntax is ASN_INTEGER
1668  *    The value is one of  unicast(1), anycast(2), broadcast(3)
1669  *
1670  * If there a no other checks you need to do, simply return MFD_SUCCESS.
1671  *
1672  */
1673 int
ipAddressType_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressType_val)1674 ipAddressType_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,
1675                           u_long ipAddressType_val)
1676 {
1677     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressType_check_value",
1678                 "called\n"));
1679 
1680     /** should never get a NULL pointer */
1681     netsnmp_assert(NULL != rowreq_ctx);
1682 
1683     /*
1684      * TODO:441:o: |-> Check for valid ipAddressType value.
1685      *
1686      * no support for anything but unicast yet
1687      */
1688     if (ipAddressType_val != IPADDRESSTYPE_UNICAST)
1689         return MFD_NOT_VALID_EVER;
1690 
1691     return MFD_SUCCESS;         /* ipAddressType value not illegal */
1692 }                               /* ipAddressType_check_value */
1693 
1694 /**
1695  * Save old value information
1696  *
1697  * @param rowreq_ctx
1698  *        Pointer to the table context (ipAddressTable_rowreq_ctx)
1699  *
1700  * @retval MFD_SUCCESS : success
1701  * @retval MFD_ERROR   : error. set will fail.
1702  *
1703  * This function will be called after the table level undo setup function
1704  * ipAddressTable_undo_setup has been called.
1705  *
1706  *@note
1707  * this function will only be called if a new value is set for this column.
1708  *
1709  * If there is any setup specific to a particular column (e.g. allocating
1710  * memory for a string), you should do that setup in this function, so it
1711  * won't be done unless it is necessary.
1712  */
1713 int
ipAddressType_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)1714 ipAddressType_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)
1715 {
1716     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressType_undo_setup",
1717                 "called\n"));
1718 
1719     /** should never get a NULL pointer */
1720     netsnmp_assert(NULL != rowreq_ctx);
1721 
1722     /*
1723      * TODO:455:o: |-> Setup ipAddressType undo.
1724      */
1725     /*
1726      * handled in ipAddressTable_undo_setup
1727      */
1728 
1729     return MFD_SUCCESS;
1730 }                               /* ipAddressType_undo_setup */
1731 
1732 /**
1733  * Set the new value.
1734  *
1735  * @param rowreq_ctx
1736  *        Pointer to the users context. You should know how to
1737  *        manipulate the value from this object.
1738  * @param ipAddressType_val
1739  *        A long containing the new value.
1740  */
1741 int
ipAddressType_set(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressType_val)1742 ipAddressType_set(ipAddressTable_rowreq_ctx * rowreq_ctx,
1743                   u_long ipAddressType_val)
1744 {
1745 
1746     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressType_set", "called\n"));
1747 
1748     /** should never get a NULL pointer */
1749     netsnmp_assert(NULL != rowreq_ctx);
1750 
1751     /*
1752      * TODO:461:M: |-> Set ipAddressType value.
1753      * set ipAddressType value in rowreq_ctx->data
1754      */
1755     rowreq_ctx->data->ia_type = ipAddressType_val;
1756 
1757     return MFD_SUCCESS;
1758 }                               /* ipAddressType_set */
1759 
1760 /**
1761  * undo the previous set.
1762  *
1763  * @param rowreq_ctx
1764  *        Pointer to the users context.
1765  */
1766 int
ipAddressType_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)1767 ipAddressType_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)
1768 {
1769 
1770     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressType_undo", "called\n"));
1771 
1772     netsnmp_assert(NULL != rowreq_ctx);
1773 
1774     /*
1775      * TODO:456:o: |-> Clean up ipAddressType undo.
1776      */
1777     /*
1778      * copy ipAddressType data
1779      * set rowreq_ctx->data->ipAddressType from rowreq_ctx->undo->ipAddressType
1780      */
1781     rowreq_ctx->data->ia_type = rowreq_ctx->undo->ia_type;
1782 
1783     return MFD_SUCCESS;
1784 }                               /* ipAddressType_undo */
1785 
1786 /*---------------------------------------------------------------------
1787  * IP-MIB::ipAddressEntry.ipAddressStatus
1788  * ipAddressStatus is subid 7 of ipAddressEntry.
1789  * Its status is Current, and its access level is Create.
1790  * OID: .1.3.6.1.2.1.4.34.1.7
1791  * Description:
1792 The status of the address, describing if the address can be
1793             used for communication.
1794 
1795 
1796             In the absence of other information, an IPv4 address is
1797             always preferred(1).
1798  *
1799  * Attributes:
1800  *   accessible 1     isscalar 0     enums  1      hasdefval 1
1801  *   readable   1     iscolumn 1     ranges 0      hashint   0
1802  *   settable   1
1803  *   defval: preferred
1804  *
1805  * Enum range: 5/8. Values:  preferred(1), invalid(3), inaccessible(4), unknown(5), tentative(6), duplicate(7)
1806  *
1807  * Its syntax is IpAddressStatusTC (based on perltype INTEGER)
1808  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
1809  */
1810 /**
1811  * Check that the proposed new value is potentially valid.
1812  *
1813  * @param rowreq_ctx
1814  *        Pointer to the row request context.
1815  * @param ipAddressStatus_val
1816  *        A long containing the new value.
1817  *
1818  * @retval MFD_SUCCESS        : incoming value is legal
1819  * @retval MFD_NOT_VALID_NOW  : incoming value is not valid now
1820  * @retval MFD_NOT_VALID_EVER : incoming value is never valid
1821  *
1822  * This is the place to check for requirements that are not
1823  * expressed in the mib syntax (for example, a requirement that
1824  * is detailed in the description for an object).
1825  *
1826  * You should check that the requested change between the undo value and the
1827  * new value is legal (ie, the transistion from one value to another
1828  * is legal).
1829  *
1830  *@note
1831  * This check is only to determine if the new value
1832  * is \b potentially valid. This is the first check of many, and
1833  * is one of the simplest ones.
1834  *
1835  *@note
1836  * this is not the place to do any checks for values
1837  * which depend on some other value in the mib. Those
1838  * types of checks should be done in the
1839  * ipAddressTable_check_dependencies() function.
1840  *
1841  * The following checks have already been done for you:
1842  *    The syntax is ASN_INTEGER
1843  *    The value is one of  preferred(1), invalid(3), inaccessible(4), unknown(5), tentative(6), duplicate(7)
1844  *
1845  * If there a no other checks you need to do, simply return MFD_SUCCESS.
1846  *
1847  */
1848 int
ipAddressStatus_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressStatus_val)1849 ipAddressStatus_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,
1850                             u_long ipAddressStatus_val)
1851 {
1852     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStatus_check_value",
1853                 "called\n"));
1854 
1855     /** should never get a NULL pointer */
1856     netsnmp_assert(NULL != rowreq_ctx);
1857 
1858     /*
1859      * TODO:441:o: |-> Check for valid ipAddressStatus value.
1860      *
1861      * nothing but preferred supported yet
1862      */
1863     if (IPADDRESSSTATUSTC_PREFERRED != ipAddressStatus_val)
1864         return MFD_NOT_VALID_EVER;
1865 
1866     return MFD_SUCCESS;         /* ipAddressStatus value not illegal */
1867 }                               /* ipAddressStatus_check_value */
1868 
1869 /**
1870  * Save old value information
1871  *
1872  * @param rowreq_ctx
1873  *        Pointer to the table context (ipAddressTable_rowreq_ctx)
1874  *
1875  * @retval MFD_SUCCESS : success
1876  * @retval MFD_ERROR   : error. set will fail.
1877  *
1878  * This function will be called after the table level undo setup function
1879  * ipAddressTable_undo_setup has been called.
1880  *
1881  *@note
1882  * this function will only be called if a new value is set for this column.
1883  *
1884  * If there is any setup specific to a particular column (e.g. allocating
1885  * memory for a string), you should do that setup in this function, so it
1886  * won't be done unless it is necessary.
1887  */
1888 int
ipAddressStatus_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)1889 ipAddressStatus_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)
1890 {
1891     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStatus_undo_setup",
1892                 "called\n"));
1893 
1894     /** should never get a NULL pointer */
1895     netsnmp_assert(NULL != rowreq_ctx);
1896 
1897     /*
1898      * TODO:455:o: |-> Setup ipAddressStatus undo.
1899      */
1900     /*
1901      * handled in ipAddressTable_undo_setup
1902      */
1903 
1904     return MFD_SUCCESS;
1905 }                               /* ipAddressStatus_undo_setup */
1906 
1907 /**
1908  * Set the new value.
1909  *
1910  * @param rowreq_ctx
1911  *        Pointer to the users context. You should know how to
1912  *        manipulate the value from this object.
1913  * @param ipAddressStatus_val
1914  *        A long containing the new value.
1915  */
1916 int
ipAddressStatus_set(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressStatus_val)1917 ipAddressStatus_set(ipAddressTable_rowreq_ctx * rowreq_ctx,
1918                     u_long ipAddressStatus_val)
1919 {
1920 
1921     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStatus_set", "called\n"));
1922 
1923     /** should never get a NULL pointer */
1924     netsnmp_assert(NULL != rowreq_ctx);
1925 
1926     /*
1927      * TODO:461:M: |-> Set ipAddressStatus value.
1928      * set ipAddressStatus value in rowreq_ctx->data
1929      */
1930     rowreq_ctx->data->ia_status = ipAddressStatus_val;
1931 
1932     return MFD_SUCCESS;
1933 }                               /* ipAddressStatus_set */
1934 
1935 /**
1936  * undo the previous set.
1937  *
1938  * @param rowreq_ctx
1939  *        Pointer to the users context.
1940  */
1941 int
ipAddressStatus_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)1942 ipAddressStatus_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)
1943 {
1944 
1945     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStatus_undo",
1946                 "called\n"));
1947 
1948     netsnmp_assert(NULL != rowreq_ctx);
1949 
1950     /*
1951      * TODO:456:o: |-> Clean up ipAddressStatus undo.
1952      */
1953     /*
1954      * copy ipAddressStatus data
1955      * set rowreq_ctx->data->ipAddressStatus from rowreq_ctx->undo->ipAddressStatus
1956      */
1957     rowreq_ctx->data->ia_status = rowreq_ctx->undo->ia_status;
1958 
1959     return MFD_SUCCESS;
1960 }                               /* ipAddressStatus_undo */
1961 
1962 /*---------------------------------------------------------------------
1963  * IP-MIB::ipAddressEntry.ipAddressRowStatus
1964  * ipAddressRowStatus is subid 10 of ipAddressEntry.
1965  * Its status is Current, and its access level is Create.
1966  * OID: .1.3.6.1.2.1.4.34.1.10
1967  * Description:
1968 The status of this conceptual row.
1969 
1970 
1971             The RowStatus TC requires that this DESCRIPTION clause
1972             states under which circumstances other objects in this row
1973             can be modified.  The value of this object has no effect on
1974             whether other objects in this conceptual row can be
1975             modified.
1976 
1977 
1978             A conceptual row can not be made active until the
1979             ipAddressIfIndex has been set to a valid index.
1980  *
1981  * Attributes:
1982  *   accessible 1     isscalar 0     enums  1      hasdefval 0
1983  *   readable   1     iscolumn 1     ranges 0      hashint   0
1984  *   settable   1
1985  *
1986  * Enum range: 3/8. Values:  active(1), notInService(2), notReady(3), createAndGo(4), createAndWait(5), destroy(6)
1987  *
1988  * Its syntax is RowStatus (based on perltype INTEGER)
1989  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
1990  */
1991 /**
1992  * Check that the proposed new value is potentially valid.
1993  *
1994  * @param rowreq_ctx
1995  *        Pointer to the row request context.
1996  * @param ipAddressRowStatus_val
1997  *        A long containing the new value.
1998  *
1999  * @retval MFD_SUCCESS        : incoming value is legal
2000  * @retval MFD_NOT_VALID_NOW  : incoming value is not valid now
2001  * @retval MFD_NOT_VALID_EVER : incoming value is never valid
2002  *
2003  * This is the place to check for requirements that are not
2004  * expressed in the mib syntax (for example, a requirement that
2005  * is detailed in the description for an object).
2006  *
2007  * You should check that the requested change between the undo value and the
2008  * new value is legal (ie, the transistion from one value to another
2009  * is legal).
2010  *
2011  *@note
2012  * This check is only to determine if the new value
2013  * is \b potentially valid. This is the first check of many, and
2014  * is one of the simplest ones.
2015  *
2016  *@note
2017  * this is not the place to do any checks for values
2018  * which depend on some other value in the mib. Those
2019  * types of checks should be done in the
2020  * ipAddressTable_check_dependencies() function.
2021  *
2022  * The following checks have already been done for you:
2023  *    The syntax is ASN_INTEGER
2024  *    The value is one of  active(1), notInService(2), notReady(3), createAndGo(4), createAndWait(5), destroy(6)
2025  *
2026  * If there a no other checks you need to do, simply return MFD_SUCCESS.
2027  *
2028  */
2029 int
ipAddressRowStatus_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressRowStatus_val)2030 ipAddressRowStatus_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,
2031                                u_long ipAddressRowStatus_val)
2032 {
2033     int             rc;
2034 
2035     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressRowStatus_check_value",
2036                 "called\n"));
2037 
2038     /** should never get a NULL pointer */
2039     netsnmp_assert(NULL != rowreq_ctx);
2040 
2041     /*
2042      * TODO:441:o: |-> Check for valid ipAddressRowStatus value.
2043      *
2044      * don't support createAndWait
2045      * check for valid RowStatus transition (old, new)
2046      */
2047     if (ROWSTATUS_CREATEANDWAIT == ipAddressRowStatus_val) {
2048         DEBUGMSGTL(("ipAddressTable", "createAndWait not supported\n"));
2049         return MFD_NOT_VALID_EVER;
2050     }
2051 
2052     rc = check_rowstatus_transition(rowreq_ctx->ipAddressRowStatus,
2053                                     ipAddressRowStatus_val);
2054     if (MFD_SUCCESS != rc) {
2055         DEBUGMSGTL(("ipAddressTable",
2056                     "row status transition from %d to %lu\n",
2057                     rowreq_ctx->ipAddressRowStatus,
2058                     ipAddressRowStatus_val));
2059         return rc;
2060     }
2061 
2062     return MFD_SUCCESS;         /* ipAddressRowStatus value not illegal */
2063 }                               /* ipAddressRowStatus_check_value */
2064 
2065 /**
2066  * Save old value information
2067  *
2068  * @param rowreq_ctx
2069  *        Pointer to the table context (ipAddressTable_rowreq_ctx)
2070  *
2071  * @retval MFD_SUCCESS : success
2072  * @retval MFD_ERROR   : error. set will fail.
2073  *
2074  * This function will be called after the table level undo setup function
2075  * ipAddressTable_undo_setup has been called.
2076  *
2077  *@note
2078  * this function will only be called if a new value is set for this column.
2079  *
2080  * If there is any setup specific to a particular column (e.g. allocating
2081  * memory for a string), you should do that setup in this function, so it
2082  * won't be done unless it is necessary.
2083  */
2084 int
ipAddressRowStatus_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)2085 ipAddressRowStatus_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)
2086 {
2087     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressRowStatus_undo_setup",
2088                 "called\n"));
2089 
2090     /** should never get a NULL pointer */
2091     netsnmp_assert(NULL != rowreq_ctx);
2092 
2093     /*
2094      * TODO:455:o: |-> Setup ipAddressRowStatus undo.
2095      */
2096     /*
2097      * handled in ipAddressTable_undo_setup
2098      */
2099 
2100     return MFD_SUCCESS;
2101 }                               /* ipAddressRowStatus_undo_setup */
2102 
2103 /**
2104  * Set the new value.
2105  *
2106  * @param rowreq_ctx
2107  *        Pointer to the users context. You should know how to
2108  *        manipulate the value from this object.
2109  * @param ipAddressRowStatus_val
2110  *        A long containing the new value.
2111  */
2112 int
ipAddressRowStatus_set(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressRowStatus_val)2113 ipAddressRowStatus_set(ipAddressTable_rowreq_ctx * rowreq_ctx,
2114                        u_long ipAddressRowStatus_val)
2115 {
2116 
2117     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressRowStatus_set",
2118                 "called\n"));
2119 
2120     /** should never get a NULL pointer */
2121     netsnmp_assert(NULL != rowreq_ctx);
2122 
2123     /*
2124      * TODO:461:M: |-> Set ipAddressRowStatus value.
2125      * set ipAddressRowStatus value in rowreq_ctx->data
2126      */
2127     rowreq_ctx->ipAddressRowStatus = ipAddressRowStatus_val;
2128 
2129     return MFD_SUCCESS;
2130 }                               /* ipAddressRowStatus_set */
2131 
2132 /**
2133  * undo the previous set.
2134  *
2135  * @param rowreq_ctx
2136  *        Pointer to the users context.
2137  */
2138 int
ipAddressRowStatus_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)2139 ipAddressRowStatus_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)
2140 {
2141 
2142     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressRowStatus_undo",
2143                 "called\n"));
2144 
2145     netsnmp_assert(NULL != rowreq_ctx);
2146 
2147     /*
2148      * TODO:456:o: |-> Clean up ipAddressRowStatus undo.
2149      */
2150     /*
2151      * copy ipAddressRowStatus data
2152      * set rowreq_ctx->data->ipAddressRowStatus from rowreq_ctx->undo->ipAddressRowStatus
2153      */
2154     rowreq_ctx->ipAddressRowStatus = rowreq_ctx->ipAddressRowStatus_undo;
2155 
2156     return MFD_SUCCESS;
2157 }                               /* ipAddressRowStatus_undo */
2158 
2159 /*---------------------------------------------------------------------
2160  * IP-MIB::ipAddressEntry.ipAddressStorageType
2161  * ipAddressStorageType is subid 11 of ipAddressEntry.
2162  * Its status is Current, and its access level is Create.
2163  * OID: .1.3.6.1.2.1.4.34.1.11
2164  * Description:
2165 The storage type for this conceptual row.  If this object
2166             has a value of 'permanent' then no other objects are
2167             required to be able to be modified.
2168  *
2169  * Attributes:
2170  *   accessible 1     isscalar 0     enums  1      hasdefval 1
2171  *   readable   1     iscolumn 1     ranges 0      hashint   0
2172  *   settable   1
2173  *   defval: volatile
2174  *
2175  * Enum range: 4/8. Values:  other(1), volatile(2), nonVolatile(3), permanent(4), readOnly(5)
2176  *
2177  * Its syntax is StorageType (based on perltype INTEGER)
2178  * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
2179  */
2180 /**
2181  * Check that the proposed new value is potentially valid.
2182  *
2183  * @param rowreq_ctx
2184  *        Pointer to the row request context.
2185  * @param ipAddressStorageType_val
2186  *        A long containing the new value.
2187  *
2188  * @retval MFD_SUCCESS        : incoming value is legal
2189  * @retval MFD_NOT_VALID_NOW  : incoming value is not valid now
2190  * @retval MFD_NOT_VALID_EVER : incoming value is never valid
2191  *
2192  * This is the place to check for requirements that are not
2193  * expressed in the mib syntax (for example, a requirement that
2194  * is detailed in the description for an object).
2195  *
2196  * You should check that the requested change between the undo value and the
2197  * new value is legal (ie, the transistion from one value to another
2198  * is legal).
2199  *
2200  *@note
2201  * This check is only to determine if the new value
2202  * is \b potentially valid. This is the first check of many, and
2203  * is one of the simplest ones.
2204  *
2205  *@note
2206  * this is not the place to do any checks for values
2207  * which depend on some other value in the mib. Those
2208  * types of checks should be done in the
2209  * ipAddressTable_check_dependencies() function.
2210  *
2211  * The following checks have already been done for you:
2212  *    The syntax is ASN_INTEGER
2213  *    The value is one of  other(1), volatile(2), nonVolatile(3), permanent(4), readOnly(5)
2214  *
2215  * If there a no other checks you need to do, simply return MFD_SUCCESS.
2216  *
2217  */
2218 int
ipAddressStorageType_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressStorageType_val)2219 ipAddressStorageType_check_value(ipAddressTable_rowreq_ctx * rowreq_ctx,
2220                                  u_long ipAddressStorageType_val)
2221 {
2222     int             rc;
2223 
2224     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStorageType_check_value",
2225                 "called\n"));
2226 
2227     /** should never get a NULL pointer */
2228     netsnmp_assert(NULL != rowreq_ctx);
2229 
2230     /*
2231      * TODO:441:o: |-> Check for valid ipAddressStorageType value.
2232      */
2233     /*
2234      * since I don't know how the various operating systems
2235      * deal with ip addresses, and whether or not changes will
2236      * be saved on reboot, so don't allow rows to be set to anything
2237      * but volatile. I'd prefer other, but since the default for
2238      * new rows, per the mib, is volatile...
2239      *
2240      * If some industrious soul would like
2241      * non-volaltile support, the first would need to
2242      *   add it in  the data access code for their os
2243      *   define a flag bit for volatile/permanent/readonly
2244      *   set the bit in data access
2245      *   copy the bit to a new var in the rowreq_ctx (see _add_new_entry)
2246      *        with a default of volatile (for os' w/out nonvolatile support)
2247      *   update this code to use new flag
2248      */
2249     if (STORAGETYPE_VOLATILE != ipAddressStorageType_val)
2250         return MFD_NOT_VALID_EVER;
2251 
2252     /*
2253      * check for valid StorageType transition (old, new)
2254      */
2255     rc = check_storage_transition(rowreq_ctx->data->ia_storagetype,
2256                                   ipAddressStorageType_val);
2257     if (MFD_SUCCESS != rc)
2258         return rc;
2259 
2260     return MFD_SUCCESS;         /* ipAddressStorageType value not illegal */
2261 }                               /* ipAddressStorageType_check_value */
2262 
2263 /**
2264  * Save old value information
2265  *
2266  * @param rowreq_ctx
2267  *        Pointer to the table context (ipAddressTable_rowreq_ctx)
2268  *
2269  * @retval MFD_SUCCESS : success
2270  * @retval MFD_ERROR   : error. set will fail.
2271  *
2272  * This function will be called after the table level undo setup function
2273  * ipAddressTable_undo_setup has been called.
2274  *
2275  *@note
2276  * this function will only be called if a new value is set for this column.
2277  *
2278  * If there is any setup specific to a particular column (e.g. allocating
2279  * memory for a string), you should do that setup in this function, so it
2280  * won't be done unless it is necessary.
2281  */
2282 int
ipAddressStorageType_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)2283 ipAddressStorageType_undo_setup(ipAddressTable_rowreq_ctx * rowreq_ctx)
2284 {
2285     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStorageType_undo_setup",
2286                 "called\n"));
2287 
2288     /** should never get a NULL pointer */
2289     netsnmp_assert(NULL != rowreq_ctx);
2290 
2291     /*
2292      * TODO:455:o: |-> Setup ipAddressStorageType undo.
2293      */
2294     /*
2295      * handled in ipAddressTable_undo_setup
2296      */
2297 
2298     return MFD_SUCCESS;
2299 }                               /* ipAddressStorageType_undo_setup */
2300 
2301 /**
2302  * Set the new value.
2303  *
2304  * @param rowreq_ctx
2305  *        Pointer to the users context. You should know how to
2306  *        manipulate the value from this object.
2307  * @param ipAddressStorageType_val
2308  *        A long containing the new value.
2309  */
2310 int
ipAddressStorageType_set(ipAddressTable_rowreq_ctx * rowreq_ctx,u_long ipAddressStorageType_val)2311 ipAddressStorageType_set(ipAddressTable_rowreq_ctx * rowreq_ctx,
2312                          u_long ipAddressStorageType_val)
2313 {
2314 
2315     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStorageType_set",
2316                 "called\n"));
2317 
2318     /** should never get a NULL pointer */
2319     netsnmp_assert(NULL != rowreq_ctx);
2320 
2321     /*
2322      * TODO:461:M: |-> Set ipAddressStorageType value.
2323      * set ipAddressStorageType value in rowreq_ctx->data
2324      */
2325     rowreq_ctx->data->ia_storagetype = ipAddressStorageType_val;
2326 
2327     return MFD_SUCCESS;
2328 }                               /* ipAddressStorageType_set */
2329 
2330 /**
2331  * undo the previous set.
2332  *
2333  * @param rowreq_ctx
2334  *        Pointer to the users context.
2335  */
2336 int
ipAddressStorageType_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)2337 ipAddressStorageType_undo(ipAddressTable_rowreq_ctx * rowreq_ctx)
2338 {
2339 
2340     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressStorageType_undo",
2341                 "called\n"));
2342 
2343     netsnmp_assert(NULL != rowreq_ctx);
2344 
2345     /*
2346      * TODO:456:o: |-> Clean up ipAddressStorageType undo.
2347      */
2348     /*
2349      * copy ipAddressStorageType data
2350      * set rowreq_ctx->data->ipAddressStorageType from rowreq_ctx->undo->ipAddressStorageType
2351      */
2352     rowreq_ctx->data->ia_storagetype = rowreq_ctx->undo->ia_storagetype;
2353 
2354     return MFD_SUCCESS;
2355 }                               /* ipAddressStorageType_undo */
2356 
2357 /**
2358  * check dependencies
2359  *
2360  * This is useful for for tables which have dependencies between columns
2361  * (or rows, or tables). For example, two columns allocating a percentage
2362  * of something add up 100%.
2363  *
2364  * Should you need different behavior depending on which columns were
2365  * set, rowreq_ctx->column_set_flags will indicate which writeable columns were
2366  * set. The definitions for the COLUMN_*_FLAG bits can be found in
2367  * ipAddressTable.h.
2368  * A new row will have the MFD_ROW_CREATED bit set in rowreq_flags.
2369  *
2370  * @retval MFD_SUCCESS all the changes to the row are legal
2371  * @retval MFD_ERROR   one or more changes are not legal
2372  *
2373  * (see README-table-ipAddressTable if you don't have dependencies)
2374  */
2375 int
ipAddressTable_check_dependencies(ipAddressTable_rowreq_ctx * rowreq_ctx)2376 ipAddressTable_check_dependencies(ipAddressTable_rowreq_ctx * rowreq_ctx)
2377 {
2378     int             rc = MFD_SUCCESS;
2379 
2380     DEBUGMSGTL(("internal:ipAddressTable:ipAddressTable_check_dependencies", "called\n"));
2381 
2382     netsnmp_assert(NULL != rowreq_ctx);
2383 
2384     /*
2385      * TODO:470:o: Check ipAddressTable row dependencies.
2386      * check that all new value are legal and consistent with each other
2387      */
2388     /*
2389      * check RowStatus dependencies
2390      */
2391     if (rowreq_ctx->column_set_flags & COLUMN_IPADDRESSROWSTATUS_FLAG) {
2392         /*
2393          * row creation requirements
2394          */
2395         if (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED) {
2396             if (ROWSTATUS_DESTROY == rowreq_ctx->ipAddressRowStatus) {
2397                 rowreq_ctx->rowreq_flags |= MFD_ROW_DELETED;
2398             } else if (ROWSTATUS_CREATEANDGO ==
2399                        rowreq_ctx->ipAddressRowStatus) {
2400                 if ((rowreq_ctx->
2401                      column_set_flags & IPADDRESSTABLE_REQUIRED_COLS)
2402                     != IPADDRESSTABLE_REQUIRED_COLS) {
2403                     DEBUGMSGTL(("ipAddressTable",
2404                                 "required columns missing (0x%0x != 0x%0x)\n",
2405                                 rowreq_ctx->column_set_flags,
2406                                 IPADDRESSTABLE_REQUIRED_COLS));
2407                     return MFD_CANNOT_CREATE_NOW;
2408                 }
2409                 rowreq_ctx->ipAddressRowStatus = ROWSTATUS_ACTIVE;
2410             }
2411         } /* row creation */
2412         else {
2413             /*
2414              * row change requirements
2415              */
2416             /*
2417              * don't allow a destroy if any other value was changed, since
2418              * that might call data access routines with bad info.
2419              *
2420              * you may or may not require the row be notInService before it
2421              * can be destroyed.
2422              */
2423             if (ROWSTATUS_DESTROY == rowreq_ctx->ipAddressRowStatus) {
2424                 if (rowreq_ctx->
2425                     column_set_flags & ~COLUMN_IPADDRESSROWSTATUS_FLAG) {
2426                     DEBUGMSGTL(("ipAddressTable",
2427                                 "destroy must be only varbind for row\n"));
2428                     return MFD_NOT_VALID_NOW;
2429                 }
2430                 rowreq_ctx->rowreq_flags |= MFD_ROW_DELETED;
2431 
2432             }                   /* row destroy */
2433         }                       /* row change */
2434     } else {
2435         /*
2436          * must have row status to create a row
2437          */
2438         if (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED) {
2439             DEBUGMSGTL(("ipAddressTable",
2440                         "must use RowStatus to create rows\n"));
2441             return MFD_CANNOT_CREATE_NOW;
2442         }
2443     }                           /* row status not set */
2444 
2445     return rc;
2446 }                               /* ipAddressTable_check_dependencies */
2447 
2448 /** @} */
2449 /** @{ */
2450