net-snmp
5.4.1
|
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