1 /*
2  * DisMan Event MIB:
3  *     Implementation of the mteObjectsTable MIB interface
4  * See 'mteObjects.c' for active behaviour of this table.
5  *
6  * (based on mib2c.table_data.conf output)
7  */
8 
9 #include <net-snmp/net-snmp-config.h>
10 #include <net-snmp/net-snmp-features.h>
11 #include <net-snmp/net-snmp-includes.h>
12 #include <net-snmp/agent/net-snmp-agent-includes.h>
13 #include "disman/event/mteObjects.h"
14 #include "disman/event/mteObjectsTable.h"
15 
16 netsnmp_feature_require(table_tdata);
17 #ifndef NETSNMP_NO_WRITE_SUPPORT
18 netsnmp_feature_require(check_vb_oid);
19 netsnmp_feature_require(check_vb_truthvalue);
20 netsnmp_feature_require(table_tdata_insert_row);
21 #endif /* NETSNMP_NO_WRITE_SUPPORT */
22 
23 static netsnmp_table_registration_info *table_info;
24 
25 /** Initializes the mteObjectsTable module */
26 void
init_mteObjectsTable(void)27 init_mteObjectsTable(void)
28 
29 {
30     static oid mteObjectsTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 3, 1 };
31     size_t     mteObjectsTable_oid_len = OID_LENGTH(mteObjectsTable_oid);
32     netsnmp_handler_registration    *reg;
33 
34     /*
35      * Ensure the object table container is available...
36      */
37     init_objects_table_data();
38 
39     /*
40      * ... then set up the MIB interface to this table
41      */
42 #ifndef NETSNMP_NO_WRITE_SUPPORT
43     reg = netsnmp_create_handler_registration("mteObjectsTable",
44                                             mteObjectsTable_handler,
45                                             mteObjectsTable_oid,
46                                             mteObjectsTable_oid_len,
47                                             HANDLER_CAN_RWRITE);
48 #else /* !NETSNMP_NO_WRITE_SUPPORT */
49     reg = netsnmp_create_handler_registration("mteObjectsTable",
50                                             mteObjectsTable_handler,
51                                             mteObjectsTable_oid,
52                                             mteObjectsTable_oid_len,
53                                             HANDLER_CAN_RONLY);
54 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
55 
56     table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
57     netsnmp_table_helper_add_indexes(table_info,
58                                      ASN_OCTET_STR, /* index: mteOwner */
59                                      ASN_OCTET_STR, /* index: mteObjectsName */
60                                      ASN_UNSIGNED,  /* index: mteObjectsIndex */
61                                      0);
62 
63     table_info->min_column = COLUMN_MTEOBJECTSID;
64     table_info->max_column = COLUMN_MTEOBJECTSENTRYSTATUS;
65 
66 
67     netsnmp_tdata_register(reg, objects_table_data, table_info);
68 }
69 
70 void
shutdown_mteObjectsTable(void)71 shutdown_mteObjectsTable(void)
72 {
73     if (table_info) {
74 	netsnmp_table_registration_info_free(table_info);
75 	table_info = NULL;
76     }
77 }
78 
79 
80 /** handles requests for the mteObjectsTable table */
81 int
mteObjectsTable_handler(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)82 mteObjectsTable_handler(netsnmp_mib_handler *handler,
83                         netsnmp_handler_registration *reginfo,
84                         netsnmp_agent_request_info *reqinfo,
85                         netsnmp_request_info *requests)
86 {
87 
88     netsnmp_request_info       *request;
89     netsnmp_table_request_info *tinfo;
90     netsnmp_tdata_row          *row;
91     struct mteObject           *entry;
92     char mteOwner[MTE_STR1_LEN+1];
93     char mteOName[MTE_STR1_LEN+1];
94     long ret;
95 
96     DEBUGMSGTL(("disman:event:mib", "ObjTable handler (%d)\n", reqinfo->mode));
97 
98     switch (reqinfo->mode) {
99         /*
100          * Read-support (also covers GetNext requests)
101          */
102     case MODE_GET:
103         for (request = requests; request; request = request->next) {
104             if (request->processed)
105                 continue;
106 
107             entry = (struct mteObject *) netsnmp_tdata_extract_entry(request);
108             tinfo = netsnmp_extract_table_info(request);
109 
110             if (!entry) {
111                 netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
112                 continue;
113             }
114             switch (tinfo->colnum) {
115             case COLUMN_MTEOBJECTSID:
116                 snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
117                               (u_char *) entry->mteObjectID,
118                                          entry->mteObjectID_len*sizeof(oid));
119                 break;
120             case COLUMN_MTEOBJECTSIDWILDCARD:
121                 ret = (entry->flags & MTE_OBJECT_FLAG_WILD ) ?
122                            TV_TRUE : TV_FALSE;
123                 snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
124                 break;
125             case COLUMN_MTEOBJECTSENTRYSTATUS:
126                 ret = (entry->flags & MTE_OBJECT_FLAG_ACTIVE ) ?
127                            RS_ACTIVE : RS_NOTINSERVICE;
128                 snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
129                 break;
130             }
131         }
132         break;
133 
134 #ifndef NETSNMP_NO_WRITE_SUPPORT
135         /*
136          * Write-support
137          */
138     case MODE_SET_RESERVE1:
139 
140         for (request = requests; request; request = request->next) {
141             if (request->processed)
142                 continue;
143 
144             entry = (struct mteObject *) netsnmp_tdata_extract_entry(request);
145             tinfo = netsnmp_extract_table_info(request);
146 
147             switch (tinfo->colnum) {
148             case COLUMN_MTEOBJECTSID:
149                 ret = netsnmp_check_vb_oid( request->requestvb );
150                 if (ret != SNMP_ERR_NOERROR) {
151                     netsnmp_set_request_error(reqinfo, request, ret);
152                     return SNMP_ERR_NOERROR;
153                 }
154                 /*
155                  * Can't modify the OID of an active row
156                  *  (an unnecessary restriction, IMO)
157                  */
158                 if (entry &&
159                     entry->flags & MTE_OBJECT_FLAG_ACTIVE ) {
160                     netsnmp_set_request_error(reqinfo, request,
161                                               SNMP_ERR_INCONSISTENTVALUE);
162                     return SNMP_ERR_NOERROR;
163                 }
164                 break;
165             case COLUMN_MTEOBJECTSIDWILDCARD:
166                 ret = netsnmp_check_vb_truthvalue( request->requestvb );
167                 if (ret != SNMP_ERR_NOERROR) {
168                     netsnmp_set_request_error(reqinfo, request, ret);
169                     return SNMP_ERR_NOERROR;
170                 }
171                 /*
172                  * Can't modify the wildcarding of an active row
173                  *  (an unnecessary restriction, IMO)
174                  */
175                 if (entry &&
176                     entry->flags & MTE_OBJECT_FLAG_ACTIVE ) {
177                     netsnmp_set_request_error(reqinfo, request,
178                                               SNMP_ERR_INCONSISTENTVALUE);
179                     return SNMP_ERR_NOERROR;
180                 }
181                 break;
182             case COLUMN_MTEOBJECTSENTRYSTATUS:
183                 ret = netsnmp_check_vb_rowstatus(request->requestvb,
184                           (entry ? RS_ACTIVE : RS_NONEXISTENT));
185                 if (ret != SNMP_ERR_NOERROR) {
186                     netsnmp_set_request_error(reqinfo, request, ret);
187                     return SNMP_ERR_NOERROR;
188                 }
189                 /* An active row can only be deleted */
190                 if (entry &&
191                     entry->flags & MTE_OBJECT_FLAG_ACTIVE &&
192                     *request->requestvb->val.integer == RS_NOTINSERVICE ) {
193                     netsnmp_set_request_error(reqinfo, request,
194                                               SNMP_ERR_INCONSISTENTVALUE);
195                     return SNMP_ERR_NOERROR;
196                 }
197                 break;
198             default:
199                 netsnmp_set_request_error(reqinfo, request,
200                                           SNMP_ERR_NOTWRITABLE);
201                 return SNMP_ERR_NOERROR;
202             }
203         }
204         break;
205 
206     case MODE_SET_RESERVE2:
207         for (request = requests; request; request = request->next) {
208             if (request->processed)
209                 continue;
210 
211             tinfo = netsnmp_extract_table_info(request);
212 
213             switch (tinfo->colnum) {
214             case COLUMN_MTEOBJECTSENTRYSTATUS:
215                 switch (*request->requestvb->val.integer) {
216                 case RS_CREATEANDGO:
217                 case RS_CREATEANDWAIT:
218                     /*
219                      * Create an (empty) new row structure
220                      */
221                     memset(mteOwner, 0, sizeof(mteOwner));
222                     memcpy(mteOwner, tinfo->indexes->val.string,
223                                      tinfo->indexes->val_len);
224                     memset(mteOName, 0, sizeof(mteOName));
225                     memcpy(mteOName,
226                            tinfo->indexes->next_variable->val.string,
227                            tinfo->indexes->next_variable->val_len);
228                     ret = *tinfo->indexes->next_variable->next_variable->val.integer;
229 
230                     row = mteObjects_createEntry(mteOwner, mteOName, ret, 0);
231                     if (!row) {
232                         netsnmp_set_request_error(reqinfo, request,
233                                                   SNMP_ERR_RESOURCEUNAVAILABLE);
234                         return SNMP_ERR_NOERROR;
235                     }
236                     netsnmp_insert_tdata_row( request, row );
237                 }
238             }
239         }
240         break;
241 
242     case MODE_SET_FREE:
243         for (request = requests; request; request = request->next) {
244             if (request->processed)
245                 continue;
246 
247             tinfo = netsnmp_extract_table_info(request);
248 
249             switch (tinfo->colnum) {
250             case COLUMN_MTEOBJECTSENTRYSTATUS:
251                 switch (*request->requestvb->val.integer) {
252                 case RS_CREATEANDGO:
253                 case RS_CREATEANDWAIT:
254                     /*
255                      * Tidy up after a failed row creation request
256                      */
257                     entry = (struct mteObject *)
258                                 netsnmp_tdata_extract_entry(request);
259                     if (entry &&
260                       !(entry->flags & MTE_OBJECT_FLAG_VALID)) {
261                         row = (netsnmp_tdata_row *)
262                                 netsnmp_tdata_extract_row(request);
263                         mteObjects_removeEntry( row );
264                     }
265                 }
266             }
267         }
268         break;
269 
270     case MODE_SET_ACTION:
271         for (request = requests; request; request = request->next) {
272             if (request->processed)
273                 continue;
274 
275             entry = (struct mteObject *) netsnmp_tdata_extract_entry(request);
276             if (!entry) {
277                 /*
278                  * New rows must be created via the RowStatus column
279                  */
280                 netsnmp_set_request_error(reqinfo, request,
281                                           SNMP_ERR_NOCREATION);
282                                       /* or inconsistentName? */
283                 return SNMP_ERR_NOERROR;
284 
285             }
286         }
287         break;
288 
289     case MODE_SET_UNDO:
290         break;
291 
292     case MODE_SET_COMMIT:
293         /*
294          * All these assignments are "unfailable", so it's
295          *  (reasonably) safe to apply them in the Commit phase
296          */
297         for (request = requests; request; request = request->next) {
298             if (request->processed)
299                 continue;
300 
301             entry = (struct mteObject *) netsnmp_tdata_extract_entry(request);
302             tinfo = netsnmp_extract_table_info(request);
303 
304             switch (tinfo->colnum) {
305             case COLUMN_MTEOBJECTSID:
306                 memset(entry->mteObjectID, 0, sizeof(entry->mteObjectID));
307                 memcpy(entry->mteObjectID, request->requestvb->val.objid,
308                                            request->requestvb->val_len);
309                 entry->mteObjectID_len = request->requestvb->val_len/sizeof(oid);
310                 break;
311 
312             case COLUMN_MTEOBJECTSIDWILDCARD:
313                 if (*request->requestvb->val.integer == TV_TRUE)
314                     entry->flags |=  MTE_OBJECT_FLAG_WILD;
315                 else
316                     entry->flags &= ~MTE_OBJECT_FLAG_WILD;
317                 break;
318 
319             case COLUMN_MTEOBJECTSENTRYSTATUS:
320                 switch (*request->requestvb->val.integer) {
321                 case RS_ACTIVE:
322                     entry->flags |= MTE_OBJECT_FLAG_ACTIVE;
323                     break;
324                 case RS_CREATEANDGO:
325                     entry->flags |= MTE_OBJECT_FLAG_VALID;
326                     entry->flags |= MTE_OBJECT_FLAG_ACTIVE;
327                     break;
328                 case RS_CREATEANDWAIT:
329                     entry->flags |= MTE_OBJECT_FLAG_VALID;
330                     break;
331 
332                 case RS_DESTROY:
333                     row = (netsnmp_tdata_row *)
334                                netsnmp_tdata_extract_row(request);
335                     mteObjects_removeEntry(row);
336                 }
337             }
338         }
339 
340         /** set up to save persistent store */
341         snmp_store_needed(NULL);
342 
343         break;
344 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
345     }
346     return SNMP_ERR_NOERROR;
347 }
348