00001 #include <net-snmp/net-snmp-config.h> 00002 00003 #include <net-snmp/net-snmp-includes.h> 00004 #include <net-snmp/agent/net-snmp-agent-includes.h> 00005 00006 #include <net-snmp/agent/scalar_group.h> 00007 00008 #include <stdlib.h> 00009 #if HAVE_STRING_H 00010 #include <string.h> 00011 #else 00012 #include <strings.h> 00013 #endif 00014 00015 #include <net-snmp/agent/instance.h> 00016 #include <net-snmp/agent/serialize.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_group_handler(first, last)); 00052 return netsnmp_register_serialize(reginfo); 00053 } 00054 00055 00056 int 00057 netsnmp_scalar_group_helper_handler(netsnmp_mib_handler *handler, 00058 netsnmp_handler_registration *reginfo, 00059 netsnmp_agent_request_info *reqinfo, 00060 netsnmp_request_info *requests) 00061 { 00062 netsnmp_variable_list *var = requests->requestvb; 00063 00064 netsnmp_scalar_group *sgroup = (netsnmp_scalar_group *)handler->myvoid; 00065 int ret, cmp; 00066 int namelen; 00067 oid subid, root_tmp[MAX_OID_LEN], *root_save; 00068 00069 DEBUGMSGTL(("helper:scalar_group", "Got request:\n")); 00070 namelen = SNMP_MIN(requests->requestvb->name_length, 00071 reginfo->rootoid_len); 00072 cmp = snmp_oid_compare(requests->requestvb->name, namelen, 00073 reginfo->rootoid, reginfo->rootoid_len); 00074 00075 DEBUGMSGTL(( "helper:scalar_group", " cmp=%d, oid:", cmp)); 00076 DEBUGMSGOID(("helper:scalar_group", var->name, var->name_length)); 00077 DEBUGMSG(( "helper:scalar_group", "\n")); 00078 00079 /* 00080 * copy root oid to root_tmp, set instance to 0. (subid set later on) 00081 * save rootoid, since we'll replace it before calling next handler, 00082 * and need to restore it afterwards. 00083 */ 00084 memcpy(root_tmp, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid)); 00085 root_tmp[reginfo->rootoid_len + 1] = 0; 00086 root_save = reginfo->rootoid; 00087 00088 ret = SNMP_ERR_NOCREATION; 00089 switch (reqinfo->mode) { 00090 /* 00091 * The handling of "exact" requests is basically the same. 00092 * The only difference between GET and SET requests is the 00093 * error/exception to return on failure. 00094 */ 00095 case MODE_GET: 00096 ret = SNMP_NOSUCHOBJECT; 00097 /* Fallthrough */ 00098 00099 case MODE_SET_RESERVE1: 00100 case MODE_SET_RESERVE2: 00101 case MODE_SET_ACTION: 00102 case MODE_SET_COMMIT: 00103 case MODE_SET_UNDO: 00104 case MODE_SET_FREE: 00105 if (cmp != 0 || 00106 requests->requestvb->name_length <= reginfo->rootoid_len) { 00107 /* 00108 * Common prefix doesn't match, or only *just* matches 00109 * the registered root (so can't possibly match a scalar) 00110 */ 00111 netsnmp_set_request_error(reqinfo, requests, ret); 00112 return SNMP_ERR_NOERROR; 00113 } else { 00114 /* 00115 * Otherwise, 00116 * extract the object subidentifier from the request, 00117 * check this is (probably) valid, and then fudge the 00118 * registered 'rootoid' to match, before passing the 00119 * request off to the next handler ('scalar'). 00120 * 00121 * Note that we don't bother checking instance subidentifiers 00122 * here. That's left to the scalar helper. 00123 */ 00124 subid = requests->requestvb->name[reginfo->rootoid_len]; 00125 if (subid < sgroup->lbound || 00126 subid > sgroup->ubound) { 00127 netsnmp_set_request_error(reqinfo, requests, ret); 00128 return SNMP_ERR_NOERROR; 00129 } 00130 root_tmp[reginfo->rootoid_len] = subid; 00131 reginfo->rootoid_len += 2; 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 -= 2; 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->lbound) 00161 subid = sgroup->lbound; 00162 else if (subid > sgroup->ubound) 00163 return SNMP_ERR_NOERROR; 00164 00165 root_tmp[reginfo->rootoid_len] = subid; 00166 reginfo->rootoid_len += 2; 00167 reginfo->rootoid = root_tmp; 00168 ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, 00169 requests); 00170 /* 00171 * If we didn't get an answer (due to holes in the group) 00172 * set things up to retry again. 00173 */ 00174 if (!requests->delegated && 00175 (requests->requestvb->type == ASN_NULL || 00176 requests->requestvb->type == SNMP_NOSUCHOBJECT || 00177 requests->requestvb->type == SNMP_NOSUCHINSTANCE)) { 00178 snmp_set_var_objid(requests->requestvb, 00179 reginfo->rootoid, reginfo->rootoid_len - 1); 00180 requests->requestvb->name[reginfo->rootoid_len - 2] = ++subid; 00181 requests->requestvb->type = ASN_PRIV_RETRY; 00182 } 00183 reginfo->rootoid = root_save; 00184 reginfo->rootoid_len -= 2; 00185 return ret; 00186 } 00187 /* 00188 * got here only if illegal mode found 00189 */ 00190 return SNMP_ERR_GENERR; 00191 } 00192
1.5.7.1
Last modified: Tuesday, 23-Dec-2025 17:22:04 UTC
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.