1 /*
2  * Note: this file originally auto-generated by mib2c using
3  *       version : 1.67 $ of : mfd-interface.m2c,v $
4  *
5  * $Id$
6  */
7 /*
8  * *********************************************************************
9  * *********************************************************************
10  * *********************************************************************
11  * ***                                                               ***
12  * ***  NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE  ***
13  * ***                                                               ***
14  * ***                                                               ***
15  * ***       THIS FILE DOES NOT CONTAIN ANY USER EDITABLE CODE.      ***
16  * ***                                                               ***
17  * ***                                                               ***
18  * ***       THE GENERATED CODE IS INTERNAL IMPLEMENTATION, AND      ***
19  * ***                                                               ***
20  * ***                                                               ***
21  * ***    IS SUBJECT TO CHANGE WITHOUT WARNING IN FUTURE RELEASES.   ***
22  * ***                                                               ***
23  * ***                                                               ***
24  * *********************************************************************
25  * *********************************************************************
26  * *********************************************************************
27  */
28 
29 /*
30  * standard Net-SNMP includes
31  */
32 #include <net-snmp/net-snmp-config.h>
33 #include <net-snmp/net-snmp-features.h>
34 #include <net-snmp/net-snmp-includes.h>
35 #include <net-snmp/agent/net-snmp-agent-includes.h>
36 
37 /*
38  * include our parent header
39  */
40 #include "ipAddressTable.h"
41 
42 
43 #include <net-snmp/agent/table_container.h>
44 #include <net-snmp/library/container.h>
45 
46 #include "ipAddressTable_interface.h"
47 
48 #include <ctype.h>
49 
50 netsnmp_feature_child_of(ipAddressTable_external_access, libnetsnmpmibs);
51 
52 netsnmp_feature_require(row_merge);
53 netsnmp_feature_require(baby_steps);
54 netsnmp_feature_require(table_container_row_insert);
55 netsnmp_feature_require(check_all_requests_error);
56 
57 
58 netsnmp_feature_child_of(ipAddressTable_container_size, ipAddressTable_external_access);
59 netsnmp_feature_child_of(ipAddressTable_registration_set, ipAddressTable_external_access);
60 netsnmp_feature_child_of(ipAddressTable_registration_get, ipAddressTable_external_access);
61 netsnmp_feature_child_of(ipAddressTable_container_get, ipAddressTable_external_access);
62 
63 /**********************************************************************
64  **********************************************************************
65  ***
66  *** Table ipAddressTable
67  ***
68  **********************************************************************
69  **********************************************************************/
70 /*
71  * IP-MIB::ipAddressTable is subid 34 of ip.
72  * Its status is Current.
73  * OID: .1.3.6.1.2.1.4.34, length: 8
74  */
75 typedef struct ipAddressTable_interface_ctx_s {
76 
77     netsnmp_container *container;
78     netsnmp_cache  *cache;
79 
80     ipAddressTable_registration *user_ctx;
81 
82     netsnmp_table_registration_info tbl_info;
83 
84     netsnmp_baby_steps_access_methods access_multiplexer;
85 
86     u_int           table_dirty;
87 
88 } ipAddressTable_interface_ctx;
89 
90 static ipAddressTable_interface_ctx ipAddressTable_if_ctx;
91 
92 static void     _ipAddressTable_container_init(ipAddressTable_interface_ctx
93                                                * if_ctx);
94 static void
95                 _ipAddressTable_container_shutdown(ipAddressTable_interface_ctx * if_ctx);
96 
97 #ifndef NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_CONTAINER_GET
98 netsnmp_container *
ipAddressTable_container_get(void)99 ipAddressTable_container_get(void)
100 {
101     return ipAddressTable_if_ctx.container;
102 }
103 #endif /* NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_CONTAINER_GET */
104 
105 #ifndef NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_REGISTRATION_GET
106 ipAddressTable_registration *
ipAddressTable_registration_get(void)107 ipAddressTable_registration_get(void)
108 {
109     return ipAddressTable_if_ctx.user_ctx;
110 }
111 #endif /* NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_REGISTRATION_GET */
112 
113 #ifndef NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_REGISTRATION_SET
114 ipAddressTable_registration *
ipAddressTable_registration_set(ipAddressTable_registration * newreg)115 ipAddressTable_registration_set(ipAddressTable_registration * newreg)
116 {
117     ipAddressTable_registration *old = ipAddressTable_if_ctx.user_ctx;
118     ipAddressTable_if_ctx.user_ctx = newreg;
119     return old;
120 }
121 #endif /* NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_REGISTRATION_SET */
122 
123 #ifndef NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_CONTAINER_SIZE
124 int
ipAddressTable_container_size(void)125 ipAddressTable_container_size(void)
126 {
127     return CONTAINER_SIZE(ipAddressTable_if_ctx.container);
128 }
129 #endif /* NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_CONTAINER_SIZE */
130 
131 u_int
ipAddressTable_dirty_get(void)132 ipAddressTable_dirty_get(void)
133 {
134     return ipAddressTable_if_ctx.table_dirty;
135 }
136 
137 void
ipAddressTable_dirty_set(u_int status)138 ipAddressTable_dirty_set(u_int status)
139 {
140     DEBUGMSGTL(("ipAddressTable:ipAddressTable_dirty_set",
141                 "called. was %d, now %d\n",
142                 ipAddressTable_if_ctx.table_dirty, status));
143     ipAddressTable_if_ctx.table_dirty = status;
144 }
145 
146 /*
147  * mfd multiplexer modes
148  */
149 static Netsnmp_Node_Handler _mfd_ipAddressTable_pre_request;
150 static Netsnmp_Node_Handler _mfd_ipAddressTable_post_request;
151 static Netsnmp_Node_Handler _mfd_ipAddressTable_object_lookup;
152 static Netsnmp_Node_Handler _mfd_ipAddressTable_get_values;
153 #if !(defined(NETSNMP_NO_WRITE_SUPPORT) || defined(NETSNMP_DISABLE_SET_SUPPORT))
154 static Netsnmp_Node_Handler _mfd_ipAddressTable_check_objects;
155 static Netsnmp_Node_Handler _mfd_ipAddressTable_undo_setup;
156 static Netsnmp_Node_Handler _mfd_ipAddressTable_set_values;
157 static Netsnmp_Node_Handler _mfd_ipAddressTable_undo_cleanup;
158 static Netsnmp_Node_Handler _mfd_ipAddressTable_undo_values;
159 static Netsnmp_Node_Handler _mfd_ipAddressTable_commit;
160 static Netsnmp_Node_Handler _mfd_ipAddressTable_undo_commit;
161 static Netsnmp_Node_Handler _mfd_ipAddressTable_irreversible_commit;
162 static Netsnmp_Node_Handler _mfd_ipAddressTable_check_dependencies;
163 
164 NETSNMP_STATIC_INLINE int
165                 _ipAddressTable_undo_column(ipAddressTable_rowreq_ctx * rowreq_ctx,
166                                             netsnmp_variable_list * var,
167                                             int column);
168 #endif /* NETSNMP_NO_WRITE_SUPPORT || NETSNMP_DISABLE_SET_SUPPORT */
169 
170 NETSNMP_STATIC_INLINE int
171                 _ipAddressTable_check_indexes(ipAddressTable_rowreq_ctx * rowreq_ctx);
172 
173 /**
174  * @internal
175  * Initialize the table ipAddressTable
176  *    (Define its contents and how it's structured)
177  */
178 void
_ipAddressTable_initialize_interface(ipAddressTable_registration * reg_ptr,u_long flags)179 _ipAddressTable_initialize_interface(ipAddressTable_registration * reg_ptr,
180                                      u_long flags)
181 {
182     netsnmp_baby_steps_access_methods *access_multiplexer =
183         &ipAddressTable_if_ctx.access_multiplexer;
184     netsnmp_table_registration_info *tbl_info =
185         &ipAddressTable_if_ctx.tbl_info;
186     netsnmp_handler_registration *reginfo;
187     netsnmp_mib_handler *handler;
188     int             mfd_modes = 0;
189 
190     DEBUGMSGTL(("internal:ipAddressTable:_ipAddressTable_initialize_interface", "called\n"));
191 
192 
193     /*************************************************
194      *
195      * save interface context for ipAddressTable
196      */
197     /*
198      * Setting up the table's definition
199      */
200     netsnmp_table_helper_add_indexes(tbl_info, ASN_INTEGER,
201                                                /** index: ipAddressAddrType */
202                                      ASN_OCTET_STR,
203                                                  /** index: ipAddressAddr */
204                                      0);
205 
206     /*
207      * Define the minimum and maximum accessible columns.  This
208      * optimizes retrieval.
209      */
210     tbl_info->min_column = IPADDRESSTABLE_MIN_COL;
211     tbl_info->max_column = IPADDRESSTABLE_MAX_COL;
212 
213     /*
214      * save users context
215      */
216     ipAddressTable_if_ctx.user_ctx = reg_ptr;
217 
218     /*
219      * call data access initialization code
220      */
221     ipAddressTable_init_data(reg_ptr);
222 
223     /*
224      * set up the container
225      */
226     _ipAddressTable_container_init(&ipAddressTable_if_ctx);
227     if (NULL == ipAddressTable_if_ctx.container) {
228         snmp_log(LOG_ERR,
229                  "could not initialize container for ipAddressTable\n");
230         return;
231     }
232 
233     /*
234      * access_multiplexer: REQUIRED wrapper for get request handling
235      */
236     access_multiplexer->object_lookup = _mfd_ipAddressTable_object_lookup;
237     access_multiplexer->get_values = _mfd_ipAddressTable_get_values;
238 
239     /*
240      * no wrappers yet
241      */
242     access_multiplexer->pre_request = _mfd_ipAddressTable_pre_request;
243     access_multiplexer->post_request = _mfd_ipAddressTable_post_request;
244 
245 
246 #if !(defined(NETSNMP_NO_WRITE_SUPPORT) || defined(NETSNMP_DISABLE_SET_SUPPORT))
247     /*
248      * REQUIRED wrappers for set request handling
249      */
250     access_multiplexer->object_syntax_checks =
251         _mfd_ipAddressTable_check_objects;
252     access_multiplexer->undo_setup = _mfd_ipAddressTable_undo_setup;
253     access_multiplexer->undo_cleanup = _mfd_ipAddressTable_undo_cleanup;
254     access_multiplexer->set_values = _mfd_ipAddressTable_set_values;
255     access_multiplexer->undo_sets = _mfd_ipAddressTable_undo_values;
256 
257     /*
258      * no wrappers yet
259      */
260     access_multiplexer->commit = _mfd_ipAddressTable_commit;
261     access_multiplexer->undo_commit = _mfd_ipAddressTable_undo_commit;
262     access_multiplexer->irreversible_commit =
263         _mfd_ipAddressTable_irreversible_commit;
264 
265     /*
266      * REQUIRED for tables with dependencies
267      */
268     access_multiplexer->consistency_checks =
269         _mfd_ipAddressTable_check_dependencies;
270 #endif /* NETSNMP_NO_WRITE_SUPPORT || NETSNMP_DISABLE_SET_SUPPORT */
271 
272     /*************************************************
273      *
274      * Create a registration, save our reg data, register table.
275      */
276     DEBUGMSGTL(("ipAddressTable:init_ipAddressTable",
277                 "Registering ipAddressTable as a mibs-for-dummies table.\n"));
278     handler =
279         netsnmp_baby_steps_access_multiplexer_get(access_multiplexer);
280     reginfo =
281         netsnmp_handler_registration_create("ipAddressTable", handler,
282                                             ipAddressTable_oid,
283                                             ipAddressTable_oid_size,
284                                             HANDLER_CAN_BABY_STEP |
285 #ifndef NETSNMP_DISABLE_SET_SUPPORT
286                                             HANDLER_CAN_RWRITE
287 #else
288                                             HANDLER_CAN_RONLY
289 #endif /* NETSNMP_DISABLE_SET_SUPPORT */
290                                           );
291     if (NULL == reginfo) {
292         snmp_log(LOG_ERR, "error registering table ipAddressTable\n");
293         return;
294     }
295     reginfo->my_reg_void = &ipAddressTable_if_ctx;
296 
297     /*************************************************
298      *
299      * set up baby steps handler, create it and inject it
300      */
301     if (access_multiplexer->object_lookup)
302         mfd_modes |= BABY_STEP_OBJECT_LOOKUP;
303     if (access_multiplexer->pre_request)
304         mfd_modes |= BABY_STEP_PRE_REQUEST;
305     if (access_multiplexer->post_request)
306         mfd_modes |= BABY_STEP_POST_REQUEST;
307 
308 #if !(defined(NETSNMP_NO_WRITE_SUPPORT) || defined(NETSNMP_DISABLE_SET_SUPPORT))
309     if (access_multiplexer->set_values)
310         mfd_modes |= BABY_STEP_SET_VALUES;
311     if (access_multiplexer->irreversible_commit)
312         mfd_modes |= BABY_STEP_IRREVERSIBLE_COMMIT;
313     if (access_multiplexer->object_syntax_checks)
314         mfd_modes |= BABY_STEP_CHECK_OBJECT;
315 
316     if (access_multiplexer->undo_setup)
317         mfd_modes |= BABY_STEP_UNDO_SETUP;
318     if (access_multiplexer->undo_cleanup)
319         mfd_modes |= BABY_STEP_UNDO_CLEANUP;
320     if (access_multiplexer->undo_sets)
321         mfd_modes |= BABY_STEP_UNDO_SETS;
322 
323     if (access_multiplexer->row_creation)
324         mfd_modes |= BABY_STEP_ROW_CREATE;
325     if (access_multiplexer->consistency_checks)
326         mfd_modes |= BABY_STEP_CHECK_CONSISTENCY;
327     if (access_multiplexer->commit)
328         mfd_modes |= BABY_STEP_COMMIT;
329     if (access_multiplexer->undo_commit)
330         mfd_modes |= BABY_STEP_UNDO_COMMIT;
331 #endif /* NETSNMP_NO_WRITE_SUPPORT || NETSNMP_DISABLE_SET_SUPPORT */
332 
333     handler = netsnmp_baby_steps_handler_get(mfd_modes);
334     netsnmp_inject_handler(reginfo, handler);
335 
336     /*************************************************
337      *
338      * inject row_merge helper with prefix rootoid_len + 2 (entry.col)
339      */
340     handler = netsnmp_get_row_merge_handler(reginfo->rootoid_len + 2);
341     netsnmp_inject_handler(reginfo, handler);
342 
343     /*************************************************
344      *
345      * inject container_table helper
346      */
347     handler =
348         netsnmp_container_table_handler_get(tbl_info,
349                                             ipAddressTable_if_ctx.
350                                             container,
351                                             TABLE_CONTAINER_KEY_NETSNMP_INDEX);
352     netsnmp_inject_handler(reginfo, handler);
353 
354     /*************************************************
355      *
356      * inject cache helper
357      */
358     if (NULL != ipAddressTable_if_ctx.cache) {
359         handler = netsnmp_cache_handler_get(ipAddressTable_if_ctx.cache);
360         netsnmp_inject_handler(reginfo, handler);
361     }
362 
363     /*
364      * register table
365      */
366     netsnmp_register_table(reginfo, tbl_info);
367 
368 }                               /* _ipAddressTable_initialize_interface */
369 
370 /**
371  * @internal
372  * Shutdown the table ipAddressTable
373  */
374 void
_ipAddressTable_shutdown_interface(ipAddressTable_registration * reg_ptr)375 _ipAddressTable_shutdown_interface(ipAddressTable_registration * reg_ptr)
376 {
377     /*
378      * shutdown the container
379      */
380     _ipAddressTable_container_shutdown(&ipAddressTable_if_ctx);
381 }
382 
383 void
ipAddressTable_valid_columns_set(netsnmp_column_info * vc)384 ipAddressTable_valid_columns_set(netsnmp_column_info *vc)
385 {
386     ipAddressTable_if_ctx.tbl_info.valid_columns = vc;
387 }                               /* ipAddressTable_valid_columns_set */
388 
389 /**
390  * @internal
391  * convert the index component stored in the context to an oid
392  */
393 int
ipAddressTable_index_to_oid(netsnmp_index * oid_idx,ipAddressTable_mib_index * mib_idx)394 ipAddressTable_index_to_oid(netsnmp_index * oid_idx,
395                             ipAddressTable_mib_index * mib_idx)
396 {
397     int             err = SNMP_ERR_NOERROR;
398 
399     /*
400      * temp storage for parsing indexes
401      */
402     /*
403      * ipAddressAddrType(1)/InetAddressType/ASN_INTEGER/long(u_long)//l/a/w/E/r/d/h
404      */
405     netsnmp_variable_list var_ipAddressAddrType;
406     /*
407      * ipAddressAddr(2)/InetAddress/ASN_OCTET_STR/char(char)//L/a/w/e/R/d/h
408      */
409     netsnmp_variable_list var_ipAddressAddr;
410 
411     /*
412      * set up varbinds
413      */
414     memset(&var_ipAddressAddrType, 0x00, sizeof(var_ipAddressAddrType));
415     var_ipAddressAddrType.type = ASN_INTEGER;
416     memset(&var_ipAddressAddr, 0x00, sizeof(var_ipAddressAddr));
417     var_ipAddressAddr.type = ASN_OCTET_STR;
418 
419     /*
420      * chain temp index varbinds together
421      */
422     var_ipAddressAddrType.next_variable = &var_ipAddressAddr;
423     var_ipAddressAddr.next_variable = NULL;
424 
425 
426     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_index_to_oid",
427                 "called\n"));
428 
429     /*
430      * ipAddressAddrType(1)/InetAddressType/ASN_INTEGER/long(u_long)//l/a/w/E/r/d/h
431      */
432     snmp_set_var_value(&var_ipAddressAddrType,
433                        (u_char *) & mib_idx->ipAddressAddrType,
434                        sizeof(mib_idx->ipAddressAddrType));
435 
436     /*
437      * ipAddressAddr(2)/InetAddress/ASN_OCTET_STR/char(char)//L/a/w/e/R/d/h
438      */
439     snmp_set_var_value(&var_ipAddressAddr,
440                        (u_char *) & mib_idx->ipAddressAddr,
441                        mib_idx->ipAddressAddr_len *
442                        sizeof(mib_idx->ipAddressAddr[0]));
443 
444 
445     err = build_oid_noalloc(oid_idx->oids, oid_idx->len, &oid_idx->len,
446                             NULL, 0, &var_ipAddressAddrType);
447     if (err)
448         snmp_log(LOG_ERR, "error %d converting index to oid\n", err);
449 
450     /*
451      * parsing may have allocated memory. free it.
452      */
453     snmp_reset_var_buffers(&var_ipAddressAddrType);
454 
455     return err;
456 }                               /* ipAddressTable_index_to_oid */
457 
458 /**
459  * extract ipAddressTable indexes from a netsnmp_index
460  *
461  * @retval SNMP_ERR_NOERROR  : no error
462  * @retval SNMP_ERR_GENERR   : error
463  */
464 int
ipAddressTable_index_from_oid(netsnmp_index * oid_idx,ipAddressTable_mib_index * mib_idx)465 ipAddressTable_index_from_oid(netsnmp_index * oid_idx,
466                               ipAddressTable_mib_index * mib_idx)
467 {
468     int             err = SNMP_ERR_NOERROR;
469 
470     /*
471      * temp storage for parsing indexes
472      */
473     /*
474      * ipAddressAddrType(1)/InetAddressType/ASN_INTEGER/long(u_long)//l/a/w/E/r/d/h
475      */
476     netsnmp_variable_list var_ipAddressAddrType;
477     /*
478      * ipAddressAddr(2)/InetAddress/ASN_OCTET_STR/char(char)//L/a/w/e/R/d/h
479      */
480     netsnmp_variable_list var_ipAddressAddr;
481 
482     /*
483      * set up varbinds
484      */
485     memset(&var_ipAddressAddrType, 0x00, sizeof(var_ipAddressAddrType));
486     var_ipAddressAddrType.type = ASN_INTEGER;
487     memset(&var_ipAddressAddr, 0x00, sizeof(var_ipAddressAddr));
488     var_ipAddressAddr.type = ASN_OCTET_STR;
489 
490     /*
491      * chain temp index varbinds together
492      */
493     var_ipAddressAddrType.next_variable = &var_ipAddressAddr;
494     var_ipAddressAddr.next_variable = NULL;
495 
496 
497     DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_index_from_oid",
498                 "called\n"));
499 
500     /*
501      * parse the oid into the individual index components
502      */
503     err = parse_oid_indexes(oid_idx->oids, oid_idx->len,
504                             &var_ipAddressAddrType);
505     if (err == SNMP_ERR_NOERROR) {
506         /*
507          * copy out values
508          */
509         mib_idx->ipAddressAddrType =
510             *((u_long *) var_ipAddressAddrType.val.string);
511         /*
512          * NOTE: val_len is in bytes, ipAddressAddr_len might not be
513          */
514         if (var_ipAddressAddr.val_len > sizeof(mib_idx->ipAddressAddr))
515             err = SNMP_ERR_GENERR;
516         else {
517             memcpy(mib_idx->ipAddressAddr, var_ipAddressAddr.val.string,
518                    var_ipAddressAddr.val_len);
519             mib_idx->ipAddressAddr_len =
520                 var_ipAddressAddr.val_len /
521                 sizeof(mib_idx->ipAddressAddr[0]);
522         }
523 
524 
525     }
526 
527     /*
528      * parsing may have allocated memory. free it.
529      */
530     snmp_reset_var_buffers(&var_ipAddressAddrType);
531 
532     return err;
533 }                               /* ipAddressTable_index_from_oid */
534 
535 
536 /*
537  *********************************************************************
538  * @internal
539  * allocate resources for a ipAddressTable_rowreq_ctx
540  */
541 ipAddressTable_rowreq_ctx *
ipAddressTable_allocate_rowreq_ctx(ipAddressTable_data * data,void * user_init_ctx)542 ipAddressTable_allocate_rowreq_ctx(ipAddressTable_data * data,
543                                    void *user_init_ctx)
544 {
545     ipAddressTable_rowreq_ctx *rowreq_ctx =
546         SNMP_MALLOC_TYPEDEF(ipAddressTable_rowreq_ctx);
547 
548     DEBUGMSGTL(("internal:ipAddressTable:ipAddressTable_allocate_rowreq_ctx", "called\n"));
549 
550     if (NULL == rowreq_ctx) {
551         snmp_log(LOG_ERR, "Couldn't allocate memory for a "
552                  "ipAddressTable_rowreq_ctx.\n");
553         return NULL;
554     } else {
555         if (NULL != data) {
556             /*
557              * track if we got data from user
558              */
559             rowreq_ctx->rowreq_flags |= MFD_ROW_DATA_FROM_USER;
560             rowreq_ctx->data = data;
561         } else if (NULL ==
562                    (rowreq_ctx->data = ipAddressTable_allocate_data())) {
563             SNMP_FREE(rowreq_ctx);
564             return NULL;
565         }
566     }
567 
568     /*
569      * undo context will be allocated when needed (in *_undo_setup)
570      */
571 
572     rowreq_ctx->oid_idx.oids = rowreq_ctx->oid_tmp;
573 
574     rowreq_ctx->ipAddressTable_data_list = NULL;
575 
576     /*
577      * if we allocated data, call init routine
578      */
579     if (!(rowreq_ctx->rowreq_flags & MFD_ROW_DATA_FROM_USER)) {
580         if (SNMPERR_SUCCESS !=
581             ipAddressTable_rowreq_ctx_init(rowreq_ctx, user_init_ctx)) {
582             ipAddressTable_release_rowreq_ctx(rowreq_ctx);
583             rowreq_ctx = NULL;
584         }
585     }
586 
587     return rowreq_ctx;
588 }                               /* ipAddressTable_allocate_rowreq_ctx */
589 
590 /*
591  * @internal
592  * release resources for a ipAddressTable_rowreq_ctx
593  */
594 void
ipAddressTable_release_rowreq_ctx(ipAddressTable_rowreq_ctx * rowreq_ctx)595 ipAddressTable_release_rowreq_ctx(ipAddressTable_rowreq_ctx * rowreq_ctx)
596 {
597     DEBUGMSGTL(("internal:ipAddressTable:ipAddressTable_release_rowreq_ctx", "called\n"));
598 
599     netsnmp_assert(NULL != rowreq_ctx);
600 
601     ipAddressTable_rowreq_ctx_cleanup(rowreq_ctx);
602 
603     /*
604      * for non-transient data, don't free data we got from the user
605      */
606     if ((rowreq_ctx->data) &&
607         !(rowreq_ctx->rowreq_flags & MFD_ROW_DATA_FROM_USER))
608         ipAddressTable_release_data(rowreq_ctx->data);
609 
610     if (rowreq_ctx->undo)
611         ipAddressTable_release_data(rowreq_ctx->undo);
612 
613     /*
614      * free index oid pointer
615      */
616     if (rowreq_ctx->oid_idx.oids != rowreq_ctx->oid_tmp)
617         free(rowreq_ctx->oid_idx.oids);
618 
619     SNMP_FREE(rowreq_ctx);
620 }                               /* ipAddressTable_release_rowreq_ctx */
621 
622 /**
623  * @internal
624  * wrapper
625  */
626 static int
_mfd_ipAddressTable_pre_request(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)627 _mfd_ipAddressTable_pre_request(netsnmp_mib_handler *handler,
628                                 netsnmp_handler_registration *reginfo,
629                                 netsnmp_agent_request_info *agtreq_info,
630                                 netsnmp_request_info *requests)
631 {
632     int             rc;
633 
634     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_pre_request",
635                 "called\n"));
636 
637     if (1 != netsnmp_row_merge_status_first(reginfo, agtreq_info)) {
638         DEBUGMSGTL(("internal:ipAddressTable",
639                     "skipping additional pre_request\n"));
640         return SNMP_ERR_NOERROR;
641     }
642 
643     rc = ipAddressTable_pre_request(ipAddressTable_if_ctx.user_ctx);
644     if (MFD_SUCCESS != rc) {
645         /*
646          * nothing we can do about it but log it
647          */
648         DEBUGMSGTL(("ipAddressTable", "error %d from "
649                     "ipAddressTable_pre_request\n", rc));
650         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
651     }
652 
653     return SNMP_ERR_NOERROR;
654 }                               /* _mfd_ipAddressTable_pre_request */
655 
656 /**
657  * @internal
658  * wrapper
659  */
660 static int
_mfd_ipAddressTable_post_request(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)661 _mfd_ipAddressTable_post_request(netsnmp_mib_handler *handler,
662                                  netsnmp_handler_registration *reginfo,
663                                  netsnmp_agent_request_info *agtreq_info,
664                                  netsnmp_request_info *requests)
665 {
666     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
667         netsnmp_container_table_row_extract(requests);
668     int             rc, packet_rc;
669 
670     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_post_request",
671                 "called\n"));
672 
673     /*
674      * release row context, if deleted
675      */
676     if (rowreq_ctx && (rowreq_ctx->rowreq_flags & MFD_ROW_DELETED))
677         ipAddressTable_release_rowreq_ctx(rowreq_ctx);
678 
679     /*
680      * wait for last call before calling user
681      */
682     if (1 != netsnmp_row_merge_status_last(reginfo, agtreq_info)) {
683         DEBUGMSGTL(("internal:ipAddressTable",
684                     "waiting for last post_request\n"));
685         return SNMP_ERR_NOERROR;
686     }
687 
688     packet_rc = netsnmp_check_all_requests_error(agtreq_info->asp, 0);
689     if ((MFD_SUCCESS != packet_rc) && ipAddressTable_dirty_get()) {
690         /*
691          * we shouldn't get here. the undo steps should also clear
692          * the dirty flags.
693          */
694         snmp_log(LOG_WARNING,
695                  "ipAddressTable dirty flag set in post_request "
696                  "but status != SUCCESS.\n");
697     }
698 
699     rc = ipAddressTable_post_request(ipAddressTable_if_ctx.user_ctx,
700                                      packet_rc);
701     if (MFD_SUCCESS != rc) {
702         /*
703          * nothing we can do about it but log it
704          */
705         DEBUGMSGTL(("ipAddressTable", "error %d from "
706                     "ipAddressTable_post_request\n", rc));
707     }
708 
709     return SNMP_ERR_NOERROR;
710 }                               /* _mfd_ipAddressTable_post_request */
711 
712 
713 /**
714  * @internal
715  * wrapper
716  */
717 static ipAddressTable_rowreq_ctx *
_mfd_ipAddressTable_rowreq_from_index(netsnmp_index * oid_idx,int * rc_ptr)718 _mfd_ipAddressTable_rowreq_from_index(netsnmp_index * oid_idx, int *rc_ptr)
719 {
720     ipAddressTable_rowreq_ctx *rowreq_ctx;
721     ipAddressTable_mib_index mib_idx;
722     int             rc;
723 
724     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_rowreq_from_index", "called\n"));
725 
726     if (NULL == rc_ptr)
727         rc_ptr = &rc;
728     *rc_ptr = MFD_SUCCESS;
729 
730     memset(&mib_idx, 0x0, sizeof(mib_idx));
731 
732     /*
733      * try to parse oid
734      */
735     *rc_ptr = ipAddressTable_index_from_oid(oid_idx, &mib_idx);
736     if (MFD_SUCCESS != *rc_ptr) {
737         DEBUGMSGT(("ipAddressTable", "error parsing index\n"));
738         return NULL;
739     }
740 
741     /*
742      * allocate new context
743      */
744     rowreq_ctx = ipAddressTable_allocate_rowreq_ctx(NULL, NULL);
745     if (NULL == rowreq_ctx) {
746         *rc_ptr = MFD_ERROR;
747         return NULL;            /* msg already logged */
748     }
749 
750     memcpy(&rowreq_ctx->tbl_idx, &mib_idx, sizeof(mib_idx));
751 
752     /*
753      * check indexes
754      */
755     *rc_ptr = _ipAddressTable_check_indexes(rowreq_ctx);
756     if (MFD_SUCCESS != *rc_ptr) {
757         netsnmp_assert((*rc_ptr == SNMP_ERR_NOCREATION) ||
758                        (*rc_ptr == SNMP_ERR_INCONSISTENTNAME));
759         ipAddressTable_release_rowreq_ctx(rowreq_ctx);
760         return NULL;
761     }
762 
763     /*
764      * copy indexes
765      */
766     rowreq_ctx->oid_idx.len = oid_idx->len;
767     memcpy(rowreq_ctx->oid_idx.oids, oid_idx->oids,
768            oid_idx->len * sizeof(oid));
769 
770     return rowreq_ctx;
771 }                               /* _mfd_ipAddressTable_rowreq_from_index */
772 
773 
774 /**
775  * @internal
776  * wrapper
777  */
778 static int
_mfd_ipAddressTable_object_lookup(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)779 _mfd_ipAddressTable_object_lookup(netsnmp_mib_handler *handler,
780                                   netsnmp_handler_registration *reginfo,
781                                   netsnmp_agent_request_info *agtreq_info,
782                                   netsnmp_request_info *requests)
783 {
784     int             rc = SNMP_ERR_NOERROR;
785     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
786         netsnmp_container_table_row_extract(requests);
787 
788     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_object_lookup", "called\n"));
789 
790     /*
791      * get our context from mfd
792      * ipAddressTable_interface_ctx *if_ctx =
793      *             (ipAddressTable_interface_ctx *)reginfo->my_reg_void;
794      */
795 
796     if (NULL == rowreq_ctx) {
797 #define NETSNMP_IPADDRESSTABLE_CREATE_SUPPORT 1
798 #ifndef NETSNMP_IPADDRESSTABLE_CREATE_SUPPORT
799         rc = SNMP_ERR_NOCREATION;
800 #else
801         netsnmp_table_request_info *tblreq_info;
802         netsnmp_index   oid_idx;
803 
804         tblreq_info = netsnmp_extract_table_info(requests);
805         if (NULL == tblreq_info) {
806             snmp_log(LOG_ERR, "request had no table info\n");
807             return MFD_ERROR;
808         }
809 
810         /*
811          * try create rowreq
812          */
813         oid_idx.oids = tblreq_info->index_oid;
814         oid_idx.len = tblreq_info->index_oid_len;
815 
816         rowreq_ctx = _mfd_ipAddressTable_rowreq_from_index(&oid_idx, &rc);
817         if (MFD_SUCCESS == rc) {
818             netsnmp_assert(NULL != rowreq_ctx);
819             rowreq_ctx->rowreq_flags |= MFD_ROW_CREATED;
820             /*
821              * add rowreq_ctx to request data lists
822              */
823             netsnmp_container_table_row_insert(requests, (netsnmp_index *)
824                                                rowreq_ctx);
825         }
826 #endif
827     }
828 
829     if (MFD_SUCCESS != rc)
830         netsnmp_request_set_error_all(requests, rc);
831     else
832         ipAddressTable_row_prep(rowreq_ctx);
833 
834     return SNMP_VALIDATE_ERR(rc);
835 }                               /* _mfd_ipAddressTable_object_lookup */
836 
837 /***********************************************************************
838  *
839  * GET processing
840  *
841  ***********************************************************************/
842 /*
843  * @internal
844  * Retrieve the value for a particular column
845  */
846 NETSNMP_STATIC_INLINE int
_ipAddressTable_get_column(ipAddressTable_rowreq_ctx * rowreq_ctx,netsnmp_variable_list * var,int column)847 _ipAddressTable_get_column(ipAddressTable_rowreq_ctx * rowreq_ctx,
848                            netsnmp_variable_list * var, int column)
849 {
850     int             rc = SNMPERR_SUCCESS;
851 
852     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_get_column",
853                 "called for %d\n", column));
854 
855 
856     netsnmp_assert(NULL != rowreq_ctx);
857 
858     switch (column) {
859 
860         /*
861          * ipAddressIfIndex(3)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/W/e/R/d/H
862          */
863     case COLUMN_IPADDRESSIFINDEX:
864         var->val_len = sizeof(long);
865         var->type = ASN_INTEGER;
866         rc = ipAddressIfIndex_get(rowreq_ctx, (long *) var->val.string);
867         break;
868 
869         /*
870          * ipAddressType(4)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
871          */
872     case COLUMN_IPADDRESSTYPE:
873         var->val_len = sizeof(u_long);
874         var->type = ASN_INTEGER;
875         rc = ipAddressType_get(rowreq_ctx, (u_long *) var->val.string);
876         break;
877 
878         /*
879          * ipAddressPrefix(5)/RowPointer/ASN_OBJECT_ID/oid(oid)//L/A/w/e/r/D/h
880          */
881     case COLUMN_IPADDRESSPREFIX:
882         var->type = ASN_OBJECT_ID;
883         rc = ipAddressPrefix_get(rowreq_ctx, (oid **) & var->val.string,
884                                  &var->val_len);
885         break;
886 
887         /*
888          * ipAddressOrigin(6)/IpAddressOriginTC/ASN_INTEGER/long(u_long)//l/A/w/E/r/d/h
889          */
890     case COLUMN_IPADDRESSORIGIN:
891         var->val_len = sizeof(u_long);
892         var->type = ASN_INTEGER;
893         rc = ipAddressOrigin_get(rowreq_ctx, (u_long *) var->val.string);
894         break;
895 
896         /*
897          * ipAddressStatus(7)/IpAddressStatusTC/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
898          */
899     case COLUMN_IPADDRESSSTATUS:
900         var->val_len = sizeof(u_long);
901         var->type = ASN_INTEGER;
902         rc = ipAddressStatus_get(rowreq_ctx, (u_long *) var->val.string);
903         break;
904 
905         /*
906          * ipAddressCreated(8)/TimeStamp/ASN_TIMETICKS/u_long(u_long)//l/A/w/e/r/d/h
907          */
908     case COLUMN_IPADDRESSCREATED:
909         var->val_len = sizeof(u_long);
910         var->type = ASN_TIMETICKS;
911         rc = ipAddressCreated_get(rowreq_ctx, (u_long *) var->val.string);
912         break;
913 
914         /*
915          * ipAddressLastChanged(9)/TimeStamp/ASN_TIMETICKS/u_long(u_long)//l/A/w/e/r/d/h
916          */
917     case COLUMN_IPADDRESSLASTCHANGED:
918         var->val_len = sizeof(u_long);
919         var->type = ASN_TIMETICKS;
920         rc = ipAddressLastChanged_get(rowreq_ctx,
921                                       (u_long *) var->val.string);
922         break;
923 
924         /*
925          * ipAddressRowStatus(10)/RowStatus/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h
926          */
927     case COLUMN_IPADDRESSROWSTATUS:
928         var->val_len = sizeof(u_long);
929         var->type = ASN_INTEGER;
930         rc = ipAddressRowStatus_get(rowreq_ctx,
931                                     (u_long *) var->val.string);
932         break;
933 
934         /*
935          * ipAddressStorageType(11)/StorageType/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
936          */
937     case COLUMN_IPADDRESSSTORAGETYPE:
938         var->val_len = sizeof(u_long);
939         var->type = ASN_INTEGER;
940         rc = ipAddressStorageType_get(rowreq_ctx,
941                                       (u_long *) var->val.string);
942         break;
943 
944     default:
945         snmp_log(LOG_ERR,
946                  "unknown column %d in _ipAddressTable_get_column\n",
947                  column);
948         break;
949     }
950 
951     return rc;
952 }                               /* _ipAddressTable_get_column */
953 
954 int
_mfd_ipAddressTable_get_values(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)955 _mfd_ipAddressTable_get_values(netsnmp_mib_handler *handler,
956                                netsnmp_handler_registration *reginfo,
957                                netsnmp_agent_request_info *agtreq_info,
958                                netsnmp_request_info *requests)
959 {
960     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
961         netsnmp_container_table_row_extract(requests);
962     netsnmp_table_request_info *tri;
963     u_char         *old_string;
964     void            (*dataFreeHook) (void *);
965     int             rc;
966 
967     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_get_values",
968                 "called\n"));
969 
970     netsnmp_assert(NULL != rowreq_ctx);
971 
972     for (; requests; requests = requests->next) {
973         /*
974          * save old pointer, so we can free it if replaced
975          */
976         old_string = requests->requestvb->val.string;
977         dataFreeHook = requests->requestvb->dataFreeHook;
978         if (NULL == requests->requestvb->val.string) {
979             requests->requestvb->val.string = requests->requestvb->buf;
980             requests->requestvb->val_len =
981                 sizeof(requests->requestvb->buf);
982         } else if (requests->requestvb->buf ==
983                    requests->requestvb->val.string) {
984             if (requests->requestvb->val_len !=
985                 sizeof(requests->requestvb->buf))
986                 requests->requestvb->val_len =
987                     sizeof(requests->requestvb->buf);
988         }
989 
990         /*
991          * get column data
992          */
993         tri = netsnmp_extract_table_info(requests);
994         if (NULL == tri)
995             continue;
996 
997         rc = _ipAddressTable_get_column(rowreq_ctx, requests->requestvb,
998                                         tri->colnum);
999         if (rc) {
1000             if (MFD_SKIP == rc) {
1001                 requests->requestvb->type = SNMP_NOSUCHINSTANCE;
1002                 rc = SNMP_ERR_NOERROR;
1003             }
1004         } else if (NULL == requests->requestvb->val.string) {
1005             snmp_log(LOG_ERR, "NULL varbind data pointer!\n");
1006             rc = SNMP_ERR_GENERR;
1007         }
1008         if (rc)
1009             netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc));
1010 
1011         /*
1012          * if the buffer wasn't used previously for the old data (i.e. it
1013          * was allcoated memory)  and the get routine replaced the pointer,
1014          * we need to free the previous pointer.
1015          */
1016         if (old_string && (old_string != requests->requestvb->buf) &&
1017             (requests->requestvb->val.string != old_string)) {
1018             if (dataFreeHook)
1019                 (*dataFreeHook) (old_string);
1020             else
1021                 free(old_string);
1022         }
1023     }                           /* for results */
1024 
1025     return SNMP_ERR_NOERROR;
1026 }                               /* _mfd_ipAddressTable_get_values */
1027 
1028 NETSNMP_STATIC_INLINE int
_ipAddressTable_check_indexes(ipAddressTable_rowreq_ctx * rowreq_ctx)1029 _ipAddressTable_check_indexes(ipAddressTable_rowreq_ctx * rowreq_ctx)
1030 {
1031     int             rc = SNMPERR_SUCCESS;
1032 
1033     DEBUGMSGTL(("internal:ipAddressTable:_ipAddressTable_check_indexes",
1034                 "called\n"));
1035 
1036     netsnmp_assert(NULL != rowreq_ctx);
1037 
1038 
1039     /*
1040      * (INDEX) ipAddressAddrType(1)/InetAddressType/ASN_INTEGER/long(u_long)//l/a/w/E/r/d/h
1041      */
1042     /*
1043      * check that the value is one of defined enums
1044      */
1045     if ((SNMPERR_SUCCESS == rc)
1046         && (rowreq_ctx->tbl_idx.ipAddressAddrType !=
1047             INETADDRESSTYPE_UNKNOWN)
1048         && (rowreq_ctx->tbl_idx.ipAddressAddrType != INETADDRESSTYPE_IPV4)
1049         && (rowreq_ctx->tbl_idx.ipAddressAddrType != INETADDRESSTYPE_IPV6)
1050         && (rowreq_ctx->tbl_idx.ipAddressAddrType != INETADDRESSTYPE_IPV4Z)
1051         && (rowreq_ctx->tbl_idx.ipAddressAddrType != INETADDRESSTYPE_IPV6Z)
1052         && (rowreq_ctx->tbl_idx.ipAddressAddrType != INETADDRESSTYPE_DNS)
1053         ) {
1054         rc = SNMP_ERR_WRONGVALUE;
1055     }
1056     if (MFD_SUCCESS != rc)
1057         return rc;
1058     rc = ipAddressAddrType_check_index(rowreq_ctx);
1059     if (MFD_SUCCESS != rc)
1060         return SNMP_ERR_NOCREATION;
1061 
1062     /*
1063      * (INDEX) ipAddressAddr(2)/InetAddress/ASN_OCTET_STR/char(char)//L/a/w/e/R/d/h
1064      */
1065     /*
1066      * check defined range(s).
1067      */
1068     if ((SNMPERR_SUCCESS == rc)
1069         && ((rowreq_ctx->tbl_idx.ipAddressAddr_len < 0)
1070             || (rowreq_ctx->tbl_idx.ipAddressAddr_len > 255))
1071         ) {
1072         rc = SNMP_ERR_WRONGLENGTH;
1073     }
1074     if (MFD_SUCCESS != rc)
1075         return rc;
1076     rc = ipAddressAddr_check_index(rowreq_ctx);
1077     if (MFD_SUCCESS != rc)
1078         return SNMP_ERR_NOCREATION;
1079 
1080     /*
1081      * if individual parts look ok, check them as a whole
1082      */
1083     return ipAddressTable_validate_index(ipAddressTable_if_ctx.user_ctx,
1084                                          rowreq_ctx);
1085 }                               /* _ipAddressTable_check_indexes */
1086 
1087 #if !(defined(NETSNMP_NO_WRITE_SUPPORT) || defined(NETSNMP_DISABLE_SET_SUPPORT))
1088 /***********************************************************************
1089  *
1090  * SET processing
1091  *
1092  ***********************************************************************/
1093 
1094 /*----------------------------------------------------------------------
1095  *
1096  * SET: Syntax checks
1097  *
1098  *---------------------------------------------------------------------*/
1099 /*
1100  * @internal
1101  * Check the syntax for a particular column
1102  */
1103 NETSNMP_STATIC_INLINE int
_ipAddressTable_check_column(ipAddressTable_rowreq_ctx * rowreq_ctx,netsnmp_variable_list * var,int column)1104 _ipAddressTable_check_column(ipAddressTable_rowreq_ctx * rowreq_ctx,
1105                              netsnmp_variable_list * var, int column)
1106 {
1107     int             rc = SNMPERR_SUCCESS;
1108 
1109     DEBUGMSGTL(("internal:ipAddressTable:_ipAddressTable_check_column",
1110                 "called for %d\n", column));
1111 
1112     netsnmp_assert(NULL != rowreq_ctx);
1113 
1114     switch (column) {
1115         /*
1116          * (INDEX) ipAddressAddrType(1)/InetAddressType/ASN_INTEGER/long(u_long)//l/a/w/E/r/d/h
1117          */
1118     case COLUMN_IPADDRESSADDRTYPE:
1119         rc = SNMP_ERR_NOTWRITABLE;      /* can not change index of active row */
1120         break;
1121         /*
1122          * (INDEX) ipAddressAddr(2)/InetAddress/ASN_OCTET_STR/char(char)//L/a/w/e/R/d/h
1123          */
1124     case COLUMN_IPADDRESSADDR:
1125         rc = SNMP_ERR_NOTWRITABLE;      /* can not change index of active row */
1126         break;
1127 
1128         /*
1129          * ipAddressIfIndex(3)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/W/e/R/d/H
1130          */
1131     case COLUMN_IPADDRESSIFINDEX:
1132         rc = netsnmp_check_vb_type(var, ASN_INTEGER);
1133         /*
1134          * check defined range(s).
1135          */
1136         if ((SNMPERR_SUCCESS == rc)
1137             && ((*var->val.integer < 1)
1138                 || (*var->val.integer > 2147483647))
1139             ) {
1140             rc = SNMP_ERR_WRONGVALUE;
1141         }
1142         if (SNMPERR_SUCCESS != rc) {
1143             DEBUGMSGTL(("ipAddressTable:_ipAddressTable_check_column:ipAddressIfIndex", "varbind validation failed (eg bad type or size)\n"));
1144         } else {
1145             rc = ipAddressIfIndex_check_value(rowreq_ctx,
1146                                               *((long *) var->val.string));
1147             if ((MFD_SUCCESS != rc) && (MFD_NOT_VALID_EVER != rc)
1148                 && (MFD_NOT_VALID_NOW != rc)) {
1149                 snmp_log(LOG_ERR,
1150                          "bad rc %d from ipAddressIfIndex_check_value\n",
1151                          rc);
1152                 rc = SNMP_ERR_GENERR;
1153             }
1154         }
1155         break;
1156 
1157         /*
1158          * ipAddressType(4)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1159          */
1160     case COLUMN_IPADDRESSTYPE:
1161         rc = netsnmp_check_vb_type(var, ASN_INTEGER);
1162         /*
1163          * check that the value is one of defined enums
1164          */
1165         if ((SNMPERR_SUCCESS == rc)
1166             && (*var->val.integer != IPADDRESSTYPE_UNICAST)
1167             && (*var->val.integer != IPADDRESSTYPE_ANYCAST)
1168             && (*var->val.integer != IPADDRESSTYPE_BROADCAST)
1169             ) {
1170             rc = SNMP_ERR_WRONGVALUE;
1171         }
1172         if (SNMPERR_SUCCESS != rc) {
1173             DEBUGMSGTL(("ipAddressTable:_ipAddressTable_check_column:ipAddressType", "varbind validation failed (eg bad type or size)\n"));
1174         } else {
1175             rc = ipAddressType_check_value(rowreq_ctx,
1176                                            *((u_long *) var->val.string));
1177             if ((MFD_SUCCESS != rc) && (MFD_NOT_VALID_EVER != rc)
1178                 && (MFD_NOT_VALID_NOW != rc)) {
1179                 snmp_log(LOG_ERR,
1180                          "bad rc %d from ipAddressType_check_value\n", rc);
1181                 rc = SNMP_ERR_GENERR;
1182             }
1183         }
1184         break;
1185 
1186         /*
1187          * ipAddressPrefix(5)/RowPointer/ASN_OBJECT_ID/oid(oid)//L/A/w/e/r/D/h
1188          */
1189     case COLUMN_IPADDRESSPREFIX:
1190         rc = SNMP_ERR_NOTWRITABLE;
1191         break;
1192 
1193         /*
1194          * ipAddressOrigin(6)/IpAddressOriginTC/ASN_INTEGER/long(u_long)//l/A/w/E/r/d/h
1195          */
1196     case COLUMN_IPADDRESSORIGIN:
1197         rc = SNMP_ERR_NOTWRITABLE;
1198         break;
1199 
1200         /*
1201          * ipAddressStatus(7)/IpAddressStatusTC/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1202          */
1203     case COLUMN_IPADDRESSSTATUS:
1204         rc = netsnmp_check_vb_type(var, ASN_INTEGER);
1205         /*
1206          * check that the value is one of defined enums
1207          */
1208         if ((SNMPERR_SUCCESS == rc)
1209             && (*var->val.integer != IPADDRESSSTATUSTC_PREFERRED)
1210             && (*var->val.integer != IPADDRESSSTATUSTC_INVALID)
1211             && (*var->val.integer != IPADDRESSSTATUSTC_INACCESSIBLE)
1212             && (*var->val.integer != IPADDRESSSTATUSTC_UNKNOWN)
1213             && (*var->val.integer != IPADDRESSSTATUSTC_TENTATIVE)
1214             && (*var->val.integer != IPADDRESSSTATUSTC_DUPLICATE)
1215             ) {
1216             rc = SNMP_ERR_WRONGVALUE;
1217         }
1218         if (SNMPERR_SUCCESS != rc) {
1219             DEBUGMSGTL(("ipAddressTable:_ipAddressTable_check_column:ipAddressStatus", "varbind validation failed (eg bad type or size)\n"));
1220         } else {
1221             rc = ipAddressStatus_check_value(rowreq_ctx,
1222                                              *((u_long *) var->val.
1223                                                string));
1224             if ((MFD_SUCCESS != rc) && (MFD_NOT_VALID_EVER != rc)
1225                 && (MFD_NOT_VALID_NOW != rc)) {
1226                 snmp_log(LOG_ERR,
1227                          "bad rc %d from ipAddressStatus_check_value\n",
1228                          rc);
1229                 rc = SNMP_ERR_GENERR;
1230             }
1231         }
1232         break;
1233 
1234         /*
1235          * ipAddressCreated(8)/TimeStamp/ASN_TIMETICKS/u_long(u_long)//l/A/w/e/r/d/h
1236          */
1237     case COLUMN_IPADDRESSCREATED:
1238         rc = SNMP_ERR_NOTWRITABLE;
1239         break;
1240 
1241         /*
1242          * ipAddressLastChanged(9)/TimeStamp/ASN_TIMETICKS/u_long(u_long)//l/A/w/e/r/d/h
1243          */
1244     case COLUMN_IPADDRESSLASTCHANGED:
1245         rc = SNMP_ERR_NOTWRITABLE;
1246         break;
1247 
1248         /*
1249          * ipAddressRowStatus(10)/RowStatus/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h
1250          */
1251     case COLUMN_IPADDRESSROWSTATUS:
1252         rc = netsnmp_check_vb_rowstatus_value(var);
1253         if (SNMPERR_SUCCESS != rc) {
1254             DEBUGMSGTL(("ipAddressTable:_ipAddressTable_check_column:ipAddressRowStatus", "varbind validation failed (eg bad type or size)\n"));
1255         } else {
1256             rc = ipAddressRowStatus_check_value(rowreq_ctx,
1257                                                 *((u_long *) var->val.
1258                                                   string));
1259             if ((MFD_SUCCESS != rc) && (MFD_NOT_VALID_EVER != rc)
1260                 && (MFD_NOT_VALID_NOW != rc)) {
1261                 snmp_log(LOG_ERR,
1262                          "bad rc %d from ipAddressRowStatus_check_value\n",
1263                          rc);
1264                 rc = SNMP_ERR_GENERR;
1265             }
1266         }
1267         break;
1268 
1269         /*
1270          * ipAddressStorageType(11)/StorageType/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1271          */
1272     case COLUMN_IPADDRESSSTORAGETYPE:
1273         rc = netsnmp_check_vb_type(var, ASN_INTEGER);
1274         /*
1275          * check that the value is one of defined enums
1276          */
1277         if ((SNMPERR_SUCCESS == rc)
1278             && (*var->val.integer != STORAGETYPE_OTHER)
1279             && (*var->val.integer != STORAGETYPE_VOLATILE)
1280             && (*var->val.integer != STORAGETYPE_NONVOLATILE)
1281             && (*var->val.integer != STORAGETYPE_PERMANENT)
1282             && (*var->val.integer != STORAGETYPE_READONLY)
1283             ) {
1284             rc = SNMP_ERR_WRONGVALUE;
1285         }
1286         if (SNMPERR_SUCCESS != rc) {
1287             DEBUGMSGTL(("ipAddressTable:_ipAddressTable_check_column:ipAddressStorageType", "varbind validation failed (eg bad type or size)\n"));
1288         } else {
1289             rc = ipAddressStorageType_check_value(rowreq_ctx,
1290                                                   *((u_long *) var->val.
1291                                                     string));
1292             if ((MFD_SUCCESS != rc) && (MFD_NOT_VALID_EVER != rc)
1293                 && (MFD_NOT_VALID_NOW != rc)) {
1294                 snmp_log(LOG_ERR,
1295                          "bad rc %d from ipAddressStorageType_check_value\n",
1296                          rc);
1297                 rc = SNMP_ERR_GENERR;
1298             }
1299         }
1300         break;
1301 
1302     default:   /** We shouldn't get here */
1303         rc = SNMP_ERR_GENERR;
1304         snmp_log(LOG_ERR,
1305                  "unknown column %d in _ipAddressTable_check_column\n",
1306                  column);
1307     }
1308 
1309     return rc;
1310 }                               /* _ipAddressTable_check_column */
1311 
1312 int
_mfd_ipAddressTable_check_objects(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1313 _mfd_ipAddressTable_check_objects(netsnmp_mib_handler *handler,
1314                                   netsnmp_handler_registration *reginfo,
1315                                   netsnmp_agent_request_info *agtreq_info,
1316                                   netsnmp_request_info *requests)
1317 {
1318     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1319         netsnmp_container_table_row_extract(requests);
1320     netsnmp_table_request_info *tri;
1321     int             rc;
1322 
1323     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_check_objects", "called\n"));
1324 
1325     netsnmp_assert(NULL != rowreq_ctx);
1326 
1327     for (; requests; requests = requests->next) {
1328 
1329         /*
1330          * get column number from table request info, and check that column
1331          */
1332         tri = netsnmp_extract_table_info(requests);
1333         if (NULL == tri)
1334             continue;
1335 
1336         rc = _ipAddressTable_check_column(rowreq_ctx, requests->requestvb,
1337                                           tri->colnum);
1338         if (rc) {
1339             netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc));
1340             break;
1341         }
1342 
1343     }                           /* for results */
1344 
1345     return SNMP_ERR_NOERROR;
1346 }                               /* _mfd_ipAddressTable_check_objects */
1347 
1348 
1349 /*----------------------------------------------------------------------
1350  *
1351  * SET: check dependencies
1352  *
1353  *---------------------------------------------------------------------*/
1354 /*
1355  * @internal
1356  * Check dependencies wrapper
1357  */
1358 static int
_mfd_ipAddressTable_check_dependencies(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1359 _mfd_ipAddressTable_check_dependencies(netsnmp_mib_handler *handler, netsnmp_handler_registration
1360                                        *reginfo, netsnmp_agent_request_info
1361                                        *agtreq_info,
1362                                        netsnmp_request_info *requests)
1363 {
1364     int             rc;
1365     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1366         netsnmp_container_table_row_extract(requests);
1367     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_check_dependencies", "called\n"));
1368 
1369     netsnmp_assert(NULL != rowreq_ctx);
1370 
1371     rc = ipAddressTable_check_dependencies(rowreq_ctx);
1372     if (rc) {
1373         DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1374                     "ipAddressTable_check_dependencies\n", rc));
1375         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
1376     }
1377 
1378     return SNMP_ERR_NOERROR;
1379 }                               /* _mfd_ipAddressTable_check_dependencies */
1380 
1381 /*----------------------------------------------------------------------
1382  *
1383  * SET: Undo setup
1384  *
1385  *---------------------------------------------------------------------*/
1386 /*
1387  * @internal
1388  * Set the value for a particular column
1389  */
1390 NETSNMP_STATIC_INLINE int
_ipAddressTable_undo_setup_column(ipAddressTable_rowreq_ctx * rowreq_ctx,int column)1391 _ipAddressTable_undo_setup_column(ipAddressTable_rowreq_ctx * rowreq_ctx,
1392                                   int column)
1393 {
1394     int             rc = SNMPERR_SUCCESS;
1395 
1396     DEBUGMSGTL(("internal:ipAddressTable:_ipAddressTable_undo_setup_column", "called for %d\n", column));
1397 
1398     netsnmp_assert(NULL != rowreq_ctx);
1399 
1400     switch (column) {
1401 
1402         /*
1403          * ipAddressIfIndex(3)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/W/e/R/d/H
1404          */
1405     case COLUMN_IPADDRESSIFINDEX:
1406         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSIFINDEX_FLAG;
1407         rc = ipAddressIfIndex_undo_setup(rowreq_ctx);
1408         break;
1409 
1410         /*
1411          * ipAddressType(4)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1412          */
1413     case COLUMN_IPADDRESSTYPE:
1414         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSTYPE_FLAG;
1415         rc = ipAddressType_undo_setup(rowreq_ctx);
1416         break;
1417 
1418         /*
1419          * ipAddressStatus(7)/IpAddressStatusTC/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1420          */
1421     case COLUMN_IPADDRESSSTATUS:
1422         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSSTATUS_FLAG;
1423         rc = ipAddressStatus_undo_setup(rowreq_ctx);
1424         break;
1425 
1426         /*
1427          * ipAddressRowStatus(10)/RowStatus/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h
1428          */
1429     case COLUMN_IPADDRESSROWSTATUS:
1430         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSROWSTATUS_FLAG;
1431         rc = ipAddressRowStatus_undo_setup(rowreq_ctx);
1432         break;
1433 
1434         /*
1435          * ipAddressStorageType(11)/StorageType/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1436          */
1437     case COLUMN_IPADDRESSSTORAGETYPE:
1438         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSSTORAGETYPE_FLAG;
1439         rc = ipAddressStorageType_undo_setup(rowreq_ctx);
1440         break;
1441 
1442     default:
1443         snmp_log(LOG_ERR,
1444                  "unknown column %d in _ipAddressTable_undo_setup_column\n",
1445                  column);
1446         break;
1447     }
1448 
1449     return rc;
1450 }                               /* _ipAddressTable_undo_setup_column */
1451 
1452 
1453 /**
1454  * @internal
1455  * undo setup
1456  */
1457 int
_mfd_ipAddressTable_undo_setup(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1458 _mfd_ipAddressTable_undo_setup(netsnmp_mib_handler *handler,
1459                                netsnmp_handler_registration *reginfo,
1460                                netsnmp_agent_request_info *agtreq_info,
1461                                netsnmp_request_info *requests)
1462 {
1463     int             rc;
1464     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1465         netsnmp_container_table_row_extract(requests);
1466 
1467     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_undo_setup",
1468                 "called\n"));
1469 
1470     netsnmp_assert(NULL != rowreq_ctx);
1471 
1472     /*
1473      * allocate undo context
1474      */
1475     rowreq_ctx->undo = ipAddressTable_allocate_data();
1476     if (NULL == rowreq_ctx->undo) {
1477         /** msg already logged */
1478         netsnmp_request_set_error_all(requests,
1479                                       SNMP_ERR_RESOURCEUNAVAILABLE);
1480         return SNMP_ERR_NOERROR;
1481     }
1482 
1483     /*
1484      * row undo setup
1485      */
1486     rowreq_ctx->column_set_flags = 0;
1487     rc = ipAddressTable_undo_setup(rowreq_ctx);
1488     if (MFD_SUCCESS != rc) {
1489         DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1490                     "ipAddressTable_undo_setup\n", rc));
1491         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
1492     } else {
1493         /*
1494          * column undo setup
1495          */
1496         netsnmp_table_request_info *tri;
1497         for (; requests; requests = requests->next) {
1498             /*
1499              * set column data
1500              */
1501             tri = netsnmp_extract_table_info(requests);
1502             if (NULL == tri)
1503                 continue;
1504 
1505             rc = _ipAddressTable_undo_setup_column(rowreq_ctx,
1506                                                    tri->colnum);
1507             if (MFD_SUCCESS != rc) {
1508                 DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1509                             "ipAddressTable_undo_setup_column\n", rc));
1510                 netsnmp_set_request_error(agtreq_info, requests,
1511                                           SNMP_VALIDATE_ERR(rc));
1512             }
1513         }                       /* for results */
1514     }
1515 
1516     return SNMP_ERR_NOERROR;
1517 }                               /* _mfd_ipAddressTable_undo_setup */
1518 
1519 /**
1520  * @internal
1521  * undo setup
1522  */
1523 int
_mfd_ipAddressTable_undo_cleanup(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1524 _mfd_ipAddressTable_undo_cleanup(netsnmp_mib_handler *handler,
1525                                  netsnmp_handler_registration *reginfo,
1526                                  netsnmp_agent_request_info *agtreq_info,
1527                                  netsnmp_request_info *requests)
1528 {
1529     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1530         netsnmp_container_table_row_extract(requests);
1531     int             rc;
1532 
1533     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_undo_cleanup",
1534                 "called\n"));
1535 
1536     /*
1537      * failed row create in early stages has no rowreq_ctx
1538      */
1539     if (NULL == rowreq_ctx)
1540         return MFD_SUCCESS;
1541 
1542     /*
1543      * call user cleanup
1544      */
1545     rc = ipAddressTable_undo_cleanup(rowreq_ctx);
1546     if (MFD_SUCCESS != rc) {
1547         /*
1548          * nothing we can do about it but log it
1549          */
1550         DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1551                     "ipAddressTable_undo_cleanup\n", rc));
1552     }
1553 
1554     /*
1555      * release undo context, if needed
1556      */
1557     if (rowreq_ctx->undo) {
1558         ipAddressTable_release_data(rowreq_ctx->undo);
1559         rowreq_ctx->undo = NULL;
1560     }
1561 
1562 
1563     return SNMP_ERR_NOERROR;
1564 }                               /* _mfd_ipAddressTable_undo_cleanup */
1565 
1566 /*----------------------------------------------------------------------
1567  *
1568  * SET: Set values
1569  *
1570  *---------------------------------------------------------------------*/
1571 /*
1572  * @internal
1573  * Set the value for a particular column
1574  */
1575 NETSNMP_STATIC_INLINE int
_ipAddressTable_set_column(ipAddressTable_rowreq_ctx * rowreq_ctx,netsnmp_variable_list * var,int column)1576 _ipAddressTable_set_column(ipAddressTable_rowreq_ctx * rowreq_ctx,
1577                            netsnmp_variable_list * var, int column)
1578 {
1579     int             rc = SNMPERR_SUCCESS;
1580 
1581     DEBUGMSGTL(("internal:ipAddressTable:_ipAddressTable_set_column",
1582                 "called for %d\n", column));
1583 
1584     netsnmp_assert(NULL != rowreq_ctx);
1585 
1586     switch (column) {
1587 
1588         /*
1589          * ipAddressIfIndex(3)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/W/e/R/d/H
1590          */
1591     case COLUMN_IPADDRESSIFINDEX:
1592         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSIFINDEX_FLAG;
1593         rc = ipAddressIfIndex_set(rowreq_ctx, *((long *) var->val.string));
1594         break;
1595 
1596         /*
1597          * ipAddressType(4)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1598          */
1599     case COLUMN_IPADDRESSTYPE:
1600         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSTYPE_FLAG;
1601         rc = ipAddressType_set(rowreq_ctx, *((u_long *) var->val.string));
1602         break;
1603 
1604         /*
1605          * ipAddressStatus(7)/IpAddressStatusTC/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1606          */
1607     case COLUMN_IPADDRESSSTATUS:
1608         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSSTATUS_FLAG;
1609         rc = ipAddressStatus_set(rowreq_ctx,
1610                                  *((u_long *) var->val.string));
1611         break;
1612 
1613         /*
1614          * ipAddressRowStatus(10)/RowStatus/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h
1615          */
1616     case COLUMN_IPADDRESSROWSTATUS:
1617         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSROWSTATUS_FLAG;
1618         rc = ipAddressRowStatus_set(rowreq_ctx,
1619                                     *((u_long *) var->val.string));
1620         break;
1621 
1622         /*
1623          * ipAddressStorageType(11)/StorageType/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1624          */
1625     case COLUMN_IPADDRESSSTORAGETYPE:
1626         rowreq_ctx->column_set_flags |= COLUMN_IPADDRESSSTORAGETYPE_FLAG;
1627         rc = ipAddressStorageType_set(rowreq_ctx,
1628                                       *((u_long *) var->val.string));
1629         break;
1630 
1631     default:
1632         snmp_log(LOG_ERR,
1633                  "unknown column %d in _ipAddressTable_set_column\n",
1634                  column);
1635         rc = SNMP_ERR_GENERR;
1636         break;
1637     }
1638 
1639     return rc;
1640 }                               /* _ipAddressTable_set_column */
1641 
1642 int
_mfd_ipAddressTable_set_values(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1643 _mfd_ipAddressTable_set_values(netsnmp_mib_handler *handler,
1644                                netsnmp_handler_registration *reginfo,
1645                                netsnmp_agent_request_info *agtreq_info,
1646                                netsnmp_request_info *requests)
1647 {
1648     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1649         netsnmp_container_table_row_extract(requests);
1650     netsnmp_table_request_info *tri;
1651     int             rc = SNMP_ERR_NOERROR;
1652 
1653     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_set_values",
1654                 "called\n"));
1655 
1656     netsnmp_assert(NULL != rowreq_ctx);
1657 
1658     rowreq_ctx->column_set_flags = 0;
1659     for (; requests; requests = requests->next) {
1660         /*
1661          * set column data
1662          */
1663         tri = netsnmp_extract_table_info(requests);
1664         if (NULL == tri)
1665             continue;
1666 
1667         rc = _ipAddressTable_set_column(rowreq_ctx,
1668                                         requests->requestvb, tri->colnum);
1669         if (MFD_SUCCESS != rc) {
1670             DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1671                         "ipAddressTable_set_column\n", rc));
1672             netsnmp_set_request_error(agtreq_info, requests,
1673                                       SNMP_VALIDATE_ERR(rc));
1674         }
1675     }                           /* for results */
1676 
1677     return SNMP_ERR_NOERROR;
1678 }                               /* _mfd_ipAddressTable_set_values */
1679 
1680 /*----------------------------------------------------------------------
1681  *
1682  * SET: commit
1683  *
1684  *---------------------------------------------------------------------*/
1685 /**
1686  * @internal
1687  * commit the values
1688  */
1689 int
_mfd_ipAddressTable_commit(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1690 _mfd_ipAddressTable_commit(netsnmp_mib_handler *handler,
1691                            netsnmp_handler_registration *reginfo,
1692                            netsnmp_agent_request_info *agtreq_info,
1693                            netsnmp_request_info *requests)
1694 {
1695     int             rc;
1696     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1697         netsnmp_container_table_row_extract(requests);
1698 
1699     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_commit",
1700                 "called\n"));
1701 
1702     netsnmp_assert(NULL != rowreq_ctx);
1703 
1704     rc = ipAddressTable_commit(rowreq_ctx);
1705     if (MFD_SUCCESS != rc) {
1706         DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1707                     "ipAddressTable_commit\n", rc));
1708         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
1709     }
1710 
1711     if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
1712         /*
1713          * if we successfully commited this row, set the dirty flag. Use the
1714          * current value + 1 (i.e. dirty = # rows changed).
1715          * this is checked in post_request...
1716          */
1717         ipAddressTable_dirty_set(ipAddressTable_dirty_get() + 1);       /* set table dirty flag */
1718     }
1719 
1720     return SNMP_ERR_NOERROR;
1721 }
1722 
1723 int
_mfd_ipAddressTable_undo_commit(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1724 _mfd_ipAddressTable_undo_commit(netsnmp_mib_handler *handler,
1725                                 netsnmp_handler_registration *reginfo,
1726                                 netsnmp_agent_request_info *agtreq_info,
1727                                 netsnmp_request_info *requests)
1728 {
1729     int             rc;
1730     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1731         netsnmp_container_table_row_extract(requests);
1732 
1733     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_undo_commit",
1734                 "called\n"));
1735 
1736     netsnmp_assert(NULL != rowreq_ctx);
1737 
1738     if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
1739         u_int           d = ipAddressTable_dirty_get();
1740 
1741         netsnmp_assert(d != 0);
1742         if (d)
1743             ipAddressTable_dirty_set(d - 1);
1744     }
1745 
1746     rc = ipAddressTable_undo_commit(rowreq_ctx);
1747     if (MFD_SUCCESS != rc) {
1748         /*
1749          * nothing we can do about it but log it
1750          */
1751         DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1752                     "ipAddressTable_undo_commit\n", rc));
1753     }
1754 
1755     if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
1756         snmp_log(LOG_WARNING,
1757                  "ipAddressTable row dirty flag still set after undo_commit\n");
1758         rowreq_ctx->rowreq_flags &= ~MFD_ROW_DIRTY;
1759     }
1760 
1761     return SNMP_ERR_NOERROR;
1762 }                               /* _mfd_ipAddressTable_commit */
1763 
1764 /*----------------------------------------------------------------------
1765  *
1766  * SET: Undo
1767  *
1768  *---------------------------------------------------------------------*/
1769 /**
1770  * @internal
1771  * undo the value for a particular column
1772  */
1773 NETSNMP_STATIC_INLINE int
_ipAddressTable_undo_column(ipAddressTable_rowreq_ctx * rowreq_ctx,netsnmp_variable_list * var,int column)1774 _ipAddressTable_undo_column(ipAddressTable_rowreq_ctx * rowreq_ctx,
1775                             netsnmp_variable_list * var, int column)
1776 {
1777     int             rc = SNMPERR_SUCCESS;
1778 
1779     DEBUGMSGTL(("internal:ipAddressTable:_ipAddressTable_undo_column",
1780                 "called for %d\n", column));
1781 
1782     netsnmp_assert(NULL != rowreq_ctx);
1783 
1784     switch (column) {
1785 
1786         /*
1787          * ipAddressIfIndex(3)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/W/e/R/d/H
1788          */
1789     case COLUMN_IPADDRESSIFINDEX:
1790         rc = ipAddressIfIndex_undo(rowreq_ctx);
1791         break;
1792 
1793         /*
1794          * ipAddressType(4)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1795          */
1796     case COLUMN_IPADDRESSTYPE:
1797         rc = ipAddressType_undo(rowreq_ctx);
1798         break;
1799 
1800         /*
1801          * ipAddressStatus(7)/IpAddressStatusTC/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1802          */
1803     case COLUMN_IPADDRESSSTATUS:
1804         rc = ipAddressStatus_undo(rowreq_ctx);
1805         break;
1806 
1807         /*
1808          * ipAddressRowStatus(10)/RowStatus/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h
1809          */
1810     case COLUMN_IPADDRESSROWSTATUS:
1811         rc = ipAddressRowStatus_undo(rowreq_ctx);
1812         break;
1813 
1814         /*
1815          * ipAddressStorageType(11)/StorageType/ASN_INTEGER/long(u_long)//l/A/W/E/r/D/h
1816          */
1817     case COLUMN_IPADDRESSSTORAGETYPE:
1818         rc = ipAddressStorageType_undo(rowreq_ctx);
1819         break;
1820 
1821     default:
1822         snmp_log(LOG_ERR,
1823                  "unknown column %d in _ipAddressTable_undo_column\n",
1824                  column);
1825         break;
1826     }
1827 
1828     return rc;
1829 }                               /* _ipAddressTable_undo_column */
1830 
1831 int
_mfd_ipAddressTable_undo_values(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1832 _mfd_ipAddressTable_undo_values(netsnmp_mib_handler *handler,
1833                                 netsnmp_handler_registration *reginfo,
1834                                 netsnmp_agent_request_info *agtreq_info,
1835                                 netsnmp_request_info *requests)
1836 {
1837     int             rc;
1838     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1839         netsnmp_container_table_row_extract(requests);
1840     netsnmp_table_request_info *tri;
1841 
1842     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_undo_values",
1843                 "called\n"));
1844 
1845     netsnmp_assert(NULL != rowreq_ctx);
1846 
1847     rc = ipAddressTable_undo(rowreq_ctx);
1848     if (MFD_SUCCESS != rc) {
1849         /*
1850          * nothing we can do about it but log it
1851          */
1852         DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1853                     "ipAddressTable_undo\n", rc));
1854     }
1855 
1856     for (; requests; requests = requests->next) {
1857         /*
1858          * set column data
1859          */
1860         tri = netsnmp_extract_table_info(requests);
1861         if (NULL == tri)
1862             continue;
1863 
1864         rc = _ipAddressTable_undo_column(rowreq_ctx, requests->requestvb,
1865                                          tri->colnum);
1866         if (MFD_SUCCESS != rc) {
1867             /*
1868              * nothing we can do about it but log it
1869              */
1870             DEBUGMSGTL(("ipAddressTable:mfd", "error %d from "
1871                         "ipAddressTable_undo_column\n", rc));
1872         }
1873     }                           /* for results */
1874 
1875     return SNMP_ERR_NOERROR;
1876 }                               /* _mfd_ipAddressTable_undo_values */
1877 
1878 /*----------------------------------------------------------------------
1879  *
1880  * SET: irreversible commit
1881  *
1882  *---------------------------------------------------------------------*/
1883 /**
1884  * @internal
1885  * commit irreversible actions
1886  */
1887 int
_mfd_ipAddressTable_irreversible_commit(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * agtreq_info,netsnmp_request_info * requests)1888 _mfd_ipAddressTable_irreversible_commit(netsnmp_mib_handler *handler, netsnmp_handler_registration
1889                                         *reginfo, netsnmp_agent_request_info
1890                                         *agtreq_info,
1891                                         netsnmp_request_info *requests)
1892 {
1893     ipAddressTable_rowreq_ctx *rowreq_ctx = (ipAddressTable_rowreq_ctx*)
1894         netsnmp_container_table_row_extract(requests);
1895 
1896     DEBUGMSGTL(("internal:ipAddressTable:_mfd_ipAddressTable_irreversible:commit", "called\n"));
1897 
1898     netsnmp_assert(NULL != rowreq_ctx);
1899 
1900     /*
1901      * check for and handle row creation/deletion
1902      * and update column exist flags...
1903      */
1904     if (rowreq_ctx->rowreq_flags & MFD_ROW_DELETED) {
1905         if (!(rowreq_ctx->rowreq_flags & MFD_ROW_CREATED))
1906             CONTAINER_REMOVE(ipAddressTable_if_ctx.container, rowreq_ctx);
1907     } else {
1908         if (rowreq_ctx->column_set_flags) {
1909             rowreq_ctx->column_set_flags = 0;
1910         }
1911         if (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED) {
1912             rowreq_ctx->rowreq_flags &= ~MFD_ROW_CREATED;
1913             CONTAINER_INSERT(ipAddressTable_if_ctx.container, rowreq_ctx);
1914         }
1915     }
1916 
1917     return SNMP_ERR_NOERROR;
1918 }                               /* _mfd_ipAddressTable_irreversible_commit */
1919 #endif /* NETSNMP_NO_WRITE_SUPPORT || NETSNMP_DISABLE_SET_SUPPORT */
1920 
1921 /***********************************************************************
1922  *
1923  * DATA ACCESS
1924  *
1925  ***********************************************************************/
1926 static void     _container_free(netsnmp_container *container);
1927 
1928 /**
1929  * @internal
1930  */
1931 static int
_cache_load(netsnmp_cache * cache,void * vmagic)1932 _cache_load(netsnmp_cache * cache, void *vmagic)
1933 {
1934     DEBUGMSGTL(("internal:ipAddressTable:_cache_load", "called\n"));
1935 
1936     if ((NULL == cache) || (NULL == cache->magic)) {
1937         snmp_log(LOG_ERR, "invalid cache for ipAddressTable_cache_load\n");
1938         return -1;
1939     }
1940 
1941     /** should only be called for an invalid or expired cache */
1942     netsnmp_assert((0 == cache->valid) || (1 == cache->expired));
1943 
1944     /*
1945      * call user code
1946      */
1947     return ipAddressTable_container_load((netsnmp_container *) cache->
1948                                          magic);
1949 }                               /* _cache_load */
1950 
1951 /**
1952  * @internal
1953  */
1954 static void
_cache_free(netsnmp_cache * cache,void * magic)1955 _cache_free(netsnmp_cache * cache, void *magic)
1956 {
1957     netsnmp_container *container;
1958 
1959     DEBUGMSGTL(("internal:ipAddressTable:_cache_free", "called\n"));
1960 
1961     if ((NULL == cache) || (NULL == cache->magic)) {
1962         snmp_log(LOG_ERR, "invalid cache in ipAddressTable_cache_free\n");
1963         return;
1964     }
1965 
1966     container = (netsnmp_container *) cache->magic;
1967 
1968     _container_free(container);
1969 }                               /* _cache_free */
1970 
1971 /**
1972  * @internal
1973  */
1974 static void
_container_item_free(ipAddressTable_rowreq_ctx * rowreq_ctx,void * context)1975 _container_item_free(ipAddressTable_rowreq_ctx * rowreq_ctx, void *context)
1976 {
1977     DEBUGMSGTL(("internal:ipAddressTable:_container_item_free",
1978                 "called\n"));
1979 
1980     if (NULL == rowreq_ctx)
1981         return;
1982 
1983     ipAddressTable_release_rowreq_ctx(rowreq_ctx);
1984 }                               /* _container_item_free */
1985 
1986 /**
1987  * @internal
1988  */
1989 static void
_container_free(netsnmp_container * container)1990 _container_free(netsnmp_container *container)
1991 {
1992     DEBUGMSGTL(("internal:ipAddressTable:_container_free", "called\n"));
1993 
1994     if (NULL == container) {
1995         snmp_log(LOG_ERR,
1996                  "invalid container in ipAddressTable_container_free\n");
1997         return;
1998     }
1999 
2000     /*
2001      * call user code
2002      */
2003     ipAddressTable_container_free(container);
2004 
2005     /*
2006      * free all items. inefficient, but easy.
2007      */
2008     CONTAINER_CLEAR(container,
2009                     (netsnmp_container_obj_func *) _container_item_free,
2010                     NULL);
2011 }                               /* _container_free */
2012 
2013 /**
2014  * @internal
2015  * initialize the container with functions or wrappers
2016  */
2017 void
_ipAddressTable_container_init(ipAddressTable_interface_ctx * if_ctx)2018 _ipAddressTable_container_init(ipAddressTable_interface_ctx * if_ctx)
2019 {
2020     DEBUGMSGTL(("internal:ipAddressTable:_ipAddressTable_container_init",
2021                 "called\n"));
2022 
2023     /*
2024      * cache init
2025      */
2026     if_ctx->cache = netsnmp_cache_create(30,    /* timeout in seconds */
2027                                          _cache_load, _cache_free,
2028                                          ipAddressTable_oid,
2029                                          ipAddressTable_oid_size);
2030 
2031     if (NULL == if_ctx->cache) {
2032         snmp_log(LOG_ERR, "error creating cache for ipAddressTable\n");
2033         return;
2034     }
2035 
2036     if_ctx->cache->flags = NETSNMP_CACHE_DONT_INVALIDATE_ON_SET;
2037 
2038     ipAddressTable_container_init(&if_ctx->container, if_ctx->cache);
2039     if (NULL == if_ctx->container)
2040         if_ctx->container =
2041             netsnmp_container_find("ipAddressTable:table_container");
2042     if (NULL == if_ctx->container) {
2043         snmp_log(LOG_ERR, "error creating container in "
2044                  "ipAddressTable_container_init\n");
2045         return;
2046     }
2047 
2048     if (NULL != if_ctx->cache)
2049         if_ctx->cache->magic = (void *) if_ctx->container;
2050 }                               /* _ipAddressTable_container_init */
2051 
2052 /**
2053  * @internal
2054  * shutdown the container with functions or wrappers
2055  */
2056 void
_ipAddressTable_container_shutdown(ipAddressTable_interface_ctx * if_ctx)2057 _ipAddressTable_container_shutdown(ipAddressTable_interface_ctx * if_ctx)
2058 {
2059     DEBUGMSGTL(("internal:ipAddressTable:_ipAddressTable_container_shutdown", "called\n"));
2060 
2061     ipAddressTable_container_shutdown(if_ctx->container);
2062 
2063     _container_free(if_ctx->container);
2064 
2065 }                               /* _ipAddressTable_container_shutdown */
2066 
2067 
2068 #ifndef NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_EXTERNAL_ACCESS
2069 ipAddressTable_rowreq_ctx *
ipAddressTable_row_find_by_mib_index(ipAddressTable_mib_index * mib_idx)2070 ipAddressTable_row_find_by_mib_index(ipAddressTable_mib_index * mib_idx)
2071 {
2072     ipAddressTable_rowreq_ctx *rowreq_ctx;
2073     oid             oid_tmp[MAX_OID_LEN];
2074     netsnmp_index   oid_idx;
2075     int             rc;
2076 
2077     /*
2078      * set up storage for OID
2079      */
2080     oid_idx.oids = oid_tmp;
2081     oid_idx.len = sizeof(oid_tmp) / sizeof(oid);
2082 
2083     /*
2084      * convert
2085      */
2086     rc = ipAddressTable_index_to_oid(&oid_idx, mib_idx);
2087     if (MFD_SUCCESS != rc)
2088         return NULL;
2089 
2090     rowreq_ctx = (ipAddressTable_rowreq_ctx*)CONTAINER_FIND(ipAddressTable_if_ctx.container, &oid_idx);
2091 
2092     return rowreq_ctx;
2093 }
2094 #endif /* NETSNMP_FEATURE_REMOVE_IPADDRESSTABLE_EXTERNAL_ACCESS */
2095