scalar_group.c

00001 #include <net-snmp/net-snmp-config.h>
00002 
00003 #include <stdlib.h>
00004 #if HAVE_STRING_H
00005 #include <string.h>
00006 #else
00007 #include <strings.h>
00008 #endif
00009 
00010 #include <net-snmp/net-snmp-includes.h>
00011 #include <net-snmp/agent/net-snmp-agent-includes.h>
00012 
00013 #include <net-snmp/agent/scalar_group.h>
00014 #include <net-snmp/agent/scalar.h>
00015 #include <net-snmp/agent/serialize.h>
00016 #include <net-snmp/agent/read_only.h>
00017 
00023 netsnmp_mib_handler *
00024 netsnmp_get_scalar_group_handler(oid first, oid last)
00025 {
00026     netsnmp_mib_handler  *ret    = NULL;
00027     netsnmp_scalar_group *sgroup = NULL;
00028 
00029     ret = netsnmp_create_handler("scalar_group",
00030                                   netsnmp_scalar_group_helper_handler);
00031     if (ret) {
00032         sgroup = SNMP_MALLOC_TYPEDEF(netsnmp_scalar_group);
00033         if (NULL == sgroup) {
00034             netsnmp_handler_free(ret);
00035             ret = NULL;
00036         }
00037         else {
00038             sgroup->lbound = first;
00039             sgroup->ubound = last;
00040             ret->myvoid = (void *)sgroup;
00041         }
00042     }
00043     return ret;
00044 }
00045 
00046 int
00047 netsnmp_register_scalar_group(netsnmp_handler_registration *reginfo,
00048                               oid first, oid last)
00049 {
00050     netsnmp_inject_handler(reginfo, netsnmp_get_instance_handler());
00051     netsnmp_inject_handler(reginfo, netsnmp_get_scalar_handler());
00052     netsnmp_inject_handler(reginfo, netsnmp_get_scalar_group_handler(first, last));
00053     return netsnmp_register_serialize(reginfo);
00054 }
00055 
00056 
00057 int
00058 netsnmp_scalar_group_helper_handler(netsnmp_mib_handler *handler,
00059                                 netsnmp_handler_registration *reginfo,
00060                                 netsnmp_agent_request_info *reqinfo,
00061                                 netsnmp_request_info *requests)
00062 {
00063     netsnmp_variable_list *var = requests->requestvb;
00064 
00065     netsnmp_scalar_group *sgroup = (netsnmp_scalar_group *)handler->myvoid;
00066     int             ret, cmp;
00067     int             namelen;
00068     oid             subid, root_tmp[MAX_OID_LEN], *root_save;
00069 
00070     DEBUGMSGTL(("helper:scalar_group", "Got request:\n"));
00071     namelen = SNMP_MIN(requests->requestvb->name_length,
00072                        reginfo->rootoid_len);
00073     cmp = snmp_oid_compare(requests->requestvb->name, namelen,
00074                            reginfo->rootoid, reginfo->rootoid_len);
00075 
00076     DEBUGMSGTL(( "helper:scalar_group", "  cmp=%d, oid:", cmp));
00077     DEBUGMSGOID(("helper:scalar_group", var->name, var->name_length));
00078     DEBUGMSG((   "helper:scalar_group", "\n"));
00079 
00080     /*
00081      * copy root oid to root_tmp, set instance to 0. (subid set later on)
00082      * save rootoid, since we'll replace it before calling next handler,
00083      * and need to restore it afterwards.
00084      */
00085     memcpy(root_tmp, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid));
00086     root_tmp[reginfo->rootoid_len + 1] = 0;
00087     root_save = reginfo->rootoid;
00088 
00089     ret = SNMP_ERR_NOCREATION;
00090     switch (reqinfo->mode) {
00091     /*
00092      * The handling of "exact" requests is basically the same.
00093      * The only difference between GET and SET requests is the
00094      *     error/exception to return on failure.
00095      */
00096     case MODE_GET:
00097         ret = SNMP_NOSUCHOBJECT;
00098         /* Fallthrough */
00099 
00100     case MODE_SET_RESERVE1:
00101     case MODE_SET_RESERVE2:
00102     case MODE_SET_ACTION:
00103     case MODE_SET_COMMIT:
00104     case MODE_SET_UNDO:
00105     case MODE_SET_FREE:
00106         if (cmp != 0 ||
00107             requests->requestvb->name_length <= reginfo->rootoid_len) {
00108             /*
00109              * Common prefix doesn't match, or only *just* matches 
00110              *  the registered root (so can't possibly match a scalar)
00111              */
00112             netsnmp_set_request_error(reqinfo, requests, ret);
00113             return SNMP_ERR_NOERROR;
00114         } else {
00115             /*
00116              * Otherwise,
00117              *     extract the object subidentifier from the request, 
00118              *     check this is (probably) valid, and then fudge the
00119              *     registered 'rootoid' to match, before passing the
00120              *     request off to the next handler ('scalar').
00121              *
00122              * Note that we don't bother checking instance subidentifiers
00123              *     here.  That's left to the scalar helper.
00124              */
00125             subid = requests->requestvb->name[reginfo->rootoid_len];
00126             if (subid < sgroup->lbound ||
00127                 subid > sgroup->ubound) {
00128                 netsnmp_set_request_error(reqinfo, requests, ret);
00129                 return SNMP_ERR_NOERROR;
00130             }
00131             root_tmp[reginfo->rootoid_len++] = subid;
00132             reginfo->rootoid = root_tmp;
00133             ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
00134                                             requests);
00135             reginfo->rootoid = root_save;
00136             reginfo->rootoid_len--;
00137             return ret;
00138         }
00139         break;
00140 
00141     case MODE_GETNEXT:
00142         /*
00143          * If we're being asked for something before (or exactly matches)
00144          *     the registered root OID, then start with the first object.
00145          * If we're being asked for something that exactly matches an object
00146          *    OID, then that's what we pass down.
00147          * Otherwise, we pass down the OID of the *next* object....
00148          */
00149         if (cmp < 0 ||
00150             requests->requestvb->name_length <= reginfo->rootoid_len) {
00151             subid  = sgroup->lbound;
00152         } else if (requests->requestvb->name_length == reginfo->rootoid_len+1)
00153             subid = requests->requestvb->name[reginfo->rootoid_len];
00154         else
00155             subid = requests->requestvb->name[reginfo->rootoid_len]+1;
00156 
00157         /*
00158          * ... always assuming this is (potentially) valid, of course.
00159          */
00160         if (subid > sgroup->ubound)
00161             return SNMP_ERR_NOERROR;
00162         
00163         root_tmp[reginfo->rootoid_len++] = subid;
00164         reginfo->rootoid = root_tmp;
00165         ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
00166                                             requests);
00167         /*
00168          * If we didn't get an answer (due to holes in the group)
00169          *   set things up to retry again.
00170          */
00171         if (!requests->delegated &&
00172             (requests->requestvb->type == ASN_NULL ||
00173              requests->requestvb->type == SNMP_NOSUCHOBJECT ||
00174              requests->requestvb->type == SNMP_NOSUCHINSTANCE)) {
00175             snmp_set_var_objid(requests->requestvb,
00176                                reginfo->rootoid, reginfo->rootoid_len);
00177             requests->requestvb->name[reginfo->rootoid_len-1] = ++subid;
00178             requests->requestvb->type = ASN_PRIV_RETRY;
00179         }
00180         reginfo->rootoid = root_save;
00181         reginfo->rootoid_len--;
00182         return ret;
00183     }
00184     /*
00185      * got here only if illegal mode found 
00186      */
00187     return SNMP_ERR_GENERR;
00188 }
00189 

net-snmpに対してSat Sep 5 13:14:23 2009に生成されました。  doxygen 1.4.7