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