agent__registry_8c-source.html from net-snmp at Krugle
Show agent__registry_8c-source.html syntax highlighted
<!--#set var="section" value="development" -->
<!--#include virtual="/page-top.html" -->
<!-- CONTENT START -->
<!-- Generated by Doxygen 1.3.9.1 -->
<div class="qindex">
<a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class=
"qindex" href="annotated.html">Data Structures</a> | <a class="qindex" href="files.html">File List</a> | <a class=
"qindex" href="functions.html">Data Fields</a> | <a class="qindex" href="pages.html">Related Pages</a> | <a class=
"qindex" href="examples.html">Examples</a>
</div>
<div class="nav">
<a class="el" href="dir_000003.html">agent</a>
</div>
<h1>agent_registry.c</h1>
<div class="fragment">
<pre class="fragment">
00001 <span class="comment">/*</span>
00002 <span class="comment"> * agent_registry.c</span>
00003 <span class="comment"> */</span>
00004 <span class="comment">/* Portions of this file are subject to the following copyright(s). See</span>
00005 <span class="comment"> * the Net-SNMP's COPYING file for more details and other copyrights</span>
00006 <span class="comment"> * that may apply:</span>
00007 <span class="comment"> */</span>
00008 <span class="comment">/*</span>
00009 <span class="comment"> * Portions of this file are copyrighted by:</span>
00010 <span class="comment"> * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.</span>
00011 <span class="comment"> * Use is subject to license terms specified in the COPYING file</span>
00012 <span class="comment"> * distributed with the Net-SNMP package.</span>
00013 <span class="comment"> */</span>
00020 <span class="preprocessor">#define IN_SNMP_VARS_C</span>
00021
00022 <span class="preprocessor">#include <net-snmp/net-snmp-config.h></span>
00023 <span class="preprocessor">#include <signal.h></span>
00024 <span class="preprocessor">#if HAVE_STRING_H</span>
00025 <span class="preprocessor">#include <string.h></span>
00026 <span class="preprocessor">#endif</span>
00027 <span class="preprocessor">#if HAVE_STDLIB_H</span>
00028 <span class="preprocessor">#include <stdlib.h></span>
00029 <span class="preprocessor">#endif</span>
00030 <span class="preprocessor">#include <sys/types.h></span>
00031 <span class="preprocessor">#include <stdio.h></span>
00032 <span class="preprocessor">#include <fcntl.h></span>
00033 <span class="preprocessor">#if HAVE_WINSOCK_H</span>
00034 <span class="preprocessor">#include <winsock.h></span>
00035 <span class="preprocessor">#endif</span>
00036 <span class="preprocessor">#if TIME_WITH_SYS_TIME</span>
00037 <span class="preprocessor"># ifdef WIN32</span>
00038 <span class="preprocessor"># include <sys/timeb.h></span>
00039 <span class="preprocessor"># else</span>
00040 <span class="preprocessor"># include <sys/time.h></span>
00041 <span class="preprocessor"># endif</span>
00042 <span class="preprocessor"># include <time.h></span>
00043 <span class="preprocessor">#else</span>
00044 <span class="preprocessor"># if HAVE_SYS_TIME_H</span>
00045 <span class="preprocessor"># include <sys/time.h></span>
00046 <span class="preprocessor"># else</span>
00047 <span class="preprocessor"># include <time.h></span>
00048 <span class="preprocessor"># endif</span>
00049 <span class="preprocessor">#endif</span>
00050 <span class="preprocessor">#if HAVE_NETINET_IN_H</span>
00051 <span class="preprocessor">#include <netinet/in.h></span>
00052 <span class="preprocessor">#endif</span>
00053
00054 <span class="preprocessor">#include <net-snmp/net-snmp-includes.h></span>
00055 <span class="preprocessor">#include <net-snmp/agent/net-snmp-agent-includes.h></span>
00056 <span class="preprocessor">#include <net-snmp/agent/agent_callbacks.h></span>
00057
00058 <span class="preprocessor">#include "snmpd.h"</span>
00059 <span class="preprocessor">#include "mibgroup/struct.h"</span>
00060 <span class="preprocessor">#include <net-snmp/agent/old_api.h></span>
00061 <span class="preprocessor">#include <net-snmp/agent/null.h></span>
00062 <span class="preprocessor">#include <net-snmp/agent/table.h></span>
00063 <span class="preprocessor">#include <net-snmp/agent/table_iterator.h></span>
00064 <span class="preprocessor">#include <net-snmp/agent/agent_registry.h></span>
00065 <span class="preprocessor">#include "mib_module_includes.h"</span>
00066
00067 <span class="preprocessor">#ifdef USING_AGENTX_SUBAGENT_MODULE</span>
00068 <span class="preprocessor">#include "agentx/subagent.h"</span>
00069 <span class="preprocessor">#include "agentx/client.h"</span>
00070 <span class="preprocessor">#endif</span>
00071
00072 <span class="keyword">static</span> <span class="keywordtype">void</span> register_mib_detach_node(netsnmp_subtree *s);
00073 NETSNMP_STATIC_INLINE <span class="keywordtype">void</span> invalidate_lookup_cache(<span class=
"keyword">const</span> <span class="keywordtype">char</span> *context);
00074 <span class="keywordtype">void</span> <a class="code" href=
"group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(<span class="keywordtype">int</span> newsize);
00075 <span class="keywordtype">int</span> <a class="code" href=
"group__agent__registry.html#ga10">netsnmp_get_lookup_cache_size</a>(<span class="keywordtype">void</span>);
00076
00077 subtree_context_cache *context_subtrees = NULL;
00078
00079 <span class="keywordtype">void</span>
00080 netsnmp_subtree_free(netsnmp_subtree *a)
00081 {
00082 <span class="keywordflow">if</span> (a != NULL) {
00083 <span class="keywordflow">if</span> (a->variables != NULL && <a class="code" href=
"group__library.html#ga106">netsnmp_oid_equals</a>(a->name_a, a->namelen,
00084 a->start_a, a->start_len) == 0) {
00085 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(a->variables);
00086 }
00087 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(a->name_a);
00088 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(a->start_a);
00089 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(a->end_a);
00090 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(a->label_a);
00091 <a class="code" href="group__handler.html#ga21">netsnmp_handler_registration_free</a>(a->reginfo);
00092 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(a);
00093 }
00094 }
00095
00096 netsnmp_subtree *
00097 netsnmp_subtree_deepcopy(netsnmp_subtree *a)
00098 {
00099 netsnmp_subtree *b = (netsnmp_subtree *)calloc(1, <span class="keyword">sizeof</span>(netsnmp_subtree));
00100
00101 <span class="keywordflow">if</span> (b != NULL) {
00102 memcpy(b, a, <span class="keyword">sizeof</span>(netsnmp_subtree));
00103 b->name_a = snmp_duplicate_objid(a->name_a, a->namelen);
00104 b->start_a = snmp_duplicate_objid(a->start_a, a->start_len);
00105 b->end_a = snmp_duplicate_objid(a->end_a, a->end_len);
00106 b->label_a = strdup(a->label_a);
00107
00108 <span class="keywordflow">if</span> (b->name_a == NULL || b->start_a == NULL ||
00109 b->end_a == NULL || b->label_a == NULL) {
00110 netsnmp_subtree_free(b);
00111 <span class="keywordflow">return</span> NULL;
00112 }
00113
00114 <span class="keywordflow">if</span> (a->variables != NULL) {
00115 b->variables = (<span class="keyword">struct </span>variable *)malloc(a->variables_len *
00116 a->variables_width);
00117 <span class="keywordflow">if</span> (b->variables != NULL) {
00118 memcpy(b->variables, a->variables,a->variables_len*a->variables_width);
00119 } <span class="keywordflow">else</span> {
00120 netsnmp_subtree_free(b);
00121 <span class="keywordflow">return</span> NULL;
00122 }
00123 }
00124
00125 <span class="keywordflow">if</span> (a->reginfo != NULL) {
00126 b->reginfo = <a class="code" href="group__handler.html#ga22">netsnmp_handler_registration_dup</a>(a->reginfo);
00127 <span class="keywordflow">if</span> (b->reginfo == NULL) {
00128 netsnmp_subtree_free(b);
00129 <span class="keywordflow">return</span> NULL;
00130 }
00131 }
00132 }
00133 <span class="keywordflow">return</span> b;
00134 }
00135
00136 subtree_context_cache *
00137 get_top_context_cache(<span class="keywordtype">void</span>)
00138 {
00139 <span class="keywordflow">return</span> context_subtrees;
00140 }
00141
00142 netsnmp_subtree *
00143 netsnmp_subtree_find_first(<span class="keyword">const</span> <span class="keywordtype">char</span> *context_name)
00144 {
00145 subtree_context_cache *ptr;
00146
00147 <span class="keywordflow">if</span> (!context_name) {
00148 context_name = <span class="stringliteral">""</span>;
00149 }
00150
00151 DEBUGMSGTL((<span class="stringliteral">"subtree"</span>, <span class=
"stringliteral">"looking for subtree for context: \"%s\"\n"</span>,
00152 context_name));
00153 <span class="keywordflow">for</span> (ptr = context_subtrees; ptr != NULL; ptr = ptr->next) {
00154 <span class="keywordflow">if</span> (ptr->context_name != NULL &&
00155 strcmp(ptr->context_name, context_name) == 0) {
00156 DEBUGMSGTL((<span class="stringliteral">"subtree"</span>, <span class=
"stringliteral">"found one for: \"%s\"\n"</span>, context_name));
00157 <span class="keywordflow">return</span> ptr->first_subtree;
00158 }
00159 }
00160 DEBUGMSGTL((<span class="stringliteral">"subtree"</span>, <span class=
"stringliteral">"didn't find a subtree for context: \"%s\"\n"</span>,
00161 context_name));
00162 <span class="keywordflow">return</span> NULL;
00163 }
00164
00165 netsnmp_subtree *
00166 add_subtree(netsnmp_subtree *new_tree, <span class="keyword">const</span> <span class=
"keywordtype">char</span> *context_name)
00167 {
00168 subtree_context_cache *ptr = <a class="code" href=
"group__util.html#ga39">SNMP_MALLOC_TYPEDEF</a>(subtree_context_cache);
00169
00170 <span class="keywordflow">if</span> (!context_name) {
00171 context_name = <span class="stringliteral">""</span>;
00172 }
00173
00174 <span class="keywordflow">if</span> (!ptr) {
00175 <span class="keywordflow">return</span> NULL;
00176 }
00177
00178 DEBUGMSGTL((<span class="stringliteral">"subtree"</span>, <span class=
"stringliteral">"adding subtree for context: \"%s\"\n"</span>,
00179 context_name));
00180
00181 ptr->next = context_subtrees;
00182 ptr->first_subtree = new_tree;
00183 ptr->context_name = strdup(context_name);
00184 context_subtrees = ptr;
00185
00186 <span class="keywordflow">return</span> ptr->first_subtree;
00187 }
00188
00189 netsnmp_subtree *
00190 netsnmp_subtree_replace_first(netsnmp_subtree *new_tree,
00191 <span class="keyword">const</span> <span class="keywordtype">char</span> *context_name)
00192 {
00193 subtree_context_cache *ptr;
00194 <span class="keywordflow">if</span> (!context_name) {
00195 context_name = <span class="stringliteral">""</span>;
00196 }
00197 <span class="keywordflow">for</span> (ptr = context_subtrees; ptr != NULL; ptr = ptr->next) {
00198 <span class="keywordflow">if</span> (ptr->context_name != NULL &&
00199 strcmp(ptr->context_name, context_name) == 0) {
00200 ptr->first_subtree = new_tree;
00201 <span class="keywordflow">return</span> ptr->first_subtree;
00202 }
00203 }
00204 <span class="keywordflow">return</span> add_subtree(new_tree, context_name);
00205 }
00206
00207 NETSNMP_INLINE <span class="keywordtype">void</span>
00208 netsnmp_subtree_change_next(netsnmp_subtree *ptr, netsnmp_subtree *thenext)
00209 {
00210 ptr->next = thenext;
00211 <span class="keywordflow">if</span> (thenext)
00212 <a class="code" href="group__library.html#ga104">netsnmp_oid_compare_ll</a>(ptr->start_a,
00213 ptr->start_len,
00214 thenext->start_a,
00215 thenext->start_len,
00216 &thenext->oid_off);
00217 }
00218
00219 NETSNMP_INLINE <span class="keywordtype">void</span>
00220 netsnmp_subtree_change_prev(netsnmp_subtree *ptr, netsnmp_subtree *theprev)
00221 {
00222 ptr->prev = theprev;
00223 <span class="keywordflow">if</span> (theprev)
00224 <a class="code" href="group__library.html#ga104">netsnmp_oid_compare_ll</a>(theprev->start_a,
00225 theprev->start_len,
00226 ptr->start_a,
00227 ptr->start_len,
00228 &ptr->oid_off);
00229 }
00230
00231 <span class="keywordtype">int</span>
00232 netsnmp_subtree_compare(<span class="keyword">const</span> netsnmp_subtree *ap, <span class=
"keyword">const</span> netsnmp_subtree *bp)
00233 {
00234 <span class="keywordflow">return</span> <a class="code" href=
"group__library.html#ga103">snmp_oid_compare</a>(ap->name_a, ap->namelen, bp->name_a, bp->namelen);
00235 }
00236
00237 <span class="keywordtype">void</span>
00238 netsnmp_subtree_join(netsnmp_subtree *root)
00239 {
00240 netsnmp_subtree *s, *tmp, *c, *d;
00241
00242 <span class="keywordflow">while</span> (root != NULL) {
00243 s = root->next;
00244 <span class="keywordflow">while</span> (s != NULL && root->reginfo == s->reginfo) {
00245 tmp = s->next;
00246 DEBUGMSGTL((<span class="stringliteral">"subtree"</span>, <span class="stringliteral">"root start "</span>));
00247 DEBUGMSGOID((<span class="stringliteral">"subtree"</span>, root->start_a, root->start_len));
00248 DEBUGMSG((<span class="stringliteral">"subtree"</span>, <span class="stringliteral">" (original end "</span>));
00249 DEBUGMSGOID((<span class="stringliteral">"subtree"</span>, root->end_a, root->end_len));
00250 DEBUGMSG((<span class="stringliteral">"subtree"</span>, <span class="stringliteral">")\n"</span>));
00251 DEBUGMSGTL((<span class="stringliteral">"subtree"</span>, <span class="stringliteral">" JOINING to "</span>));
00252 DEBUGMSGOID((<span class="stringliteral">"subtree"</span>, s->start_a, s->start_len));
00253
00254 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(root->end_a);
00255 root->end_a = s->end_a;
00256 root->end_len = s->end_len;
00257 s->end_a = NULL;
00258
00259 <span class="keywordflow">for</span> (c = root; c != NULL; c = c->children) {
00260 netsnmp_subtree_change_next(c, s->next);
00261 }
00262 <span class="keywordflow">for</span> (c = s; c != NULL; c = c->children) {
00263 netsnmp_subtree_change_prev(c, root);
00264 }
00265 DEBUGMSG((<span class="stringliteral">"subtree"</span>, <span class="stringliteral">" so new end "</span>));
00266 DEBUGMSGOID((<span class="stringliteral">"subtree"</span>, root->end_a, root->end_len));
00267 DEBUGMSG((<span class="stringliteral">"subtree"</span>, <span class="stringliteral">"\n"</span>));
00268 <span class="comment">/*</span>
00269 <span class="comment"> * Probably need to free children too? </span>
00270 <span class="comment"> */</span>
00271 <span class="keywordflow">for</span> (c = s->children; c != NULL; c = d) {
00272 d = c->children;
00273 netsnmp_subtree_free(c);
00274 }
00275 netsnmp_subtree_free(s);
00276 s = tmp;
00277 }
00278 root = root->next;
00279 }
00280 }
00281
00282
00283 <span class="comment">/*</span>
00284 <span class="comment"> * Split the subtree into two at the specified point,</span>
00285 <span class="comment"> * returning the new (second) subtree</span>
00286 <span class="comment"> */</span>
00287 netsnmp_subtree *
00288 netsnmp_subtree_split(netsnmp_subtree *current, oid name[], <span class="keywordtype">int</span> name_len)
00289 {
00290 <span class="keyword">struct </span>variable *vp = NULL;
00291 netsnmp_subtree *new_sub, *ptr;
00292 <span class="keywordtype">int</span> i = 0, rc = 0, rc2 = 0;
00293 size_t common_len = 0;
00294 <span class="keywordtype">char</span> *cp;
00295 oid *tmp_a, *tmp_b;
00296
00297 <span class="keywordflow">if</span> (<a class="code" href=
"group__library.html#ga103">snmp_oid_compare</a>(name, name_len, current->end_a, current->end_len)>0) {
00298 <span class="comment">/* Split comes after the end of this subtree */</span>
00299 <span class="keywordflow">return</span> NULL;
00300 }
00301
00302 new_sub = netsnmp_subtree_deepcopy(current);
00303 <span class="keywordflow">if</span> (new_sub == NULL) {
00304 <span class="keywordflow">return</span> NULL;
00305 }
00306
00307 <span class="comment">/* Set up the point of division. */</span>
00308 tmp_a = snmp_duplicate_objid(name, name_len);
00309 <span class="keywordflow">if</span> (tmp_a == NULL) {
00310 netsnmp_subtree_free(new_sub);
00311 <span class="keywordflow">return</span> NULL;
00312 }
00313 tmp_b = snmp_duplicate_objid(name, name_len);
00314 <span class="keywordflow">if</span> (tmp_b == NULL) {
00315 netsnmp_subtree_free(new_sub);
00316 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(tmp_a);
00317 <span class="keywordflow">return</span> NULL;
00318 }
00319
00320 <span class="keywordflow">if</span> (current->end_a != NULL) {
00321 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(current->end_a);
00322 }
00323 current->end_a = tmp_a;
00324 current->end_len = name_len;
00325 <span class="keywordflow">if</span> (new_sub->start_a != NULL) {
00326 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(new_sub->start_a);
00327 }
00328 new_sub->start_a = tmp_b;
00329 new_sub->start_len = name_len;
00330
00331 <span class="comment">/* Split the variables between the two new subtrees. */</span>
00332 i = current->variables_len;
00333 current->variables_len = 0;
00334
00335 <span class="keywordflow">for</span> (vp = current->variables; i > 0; i--) {
00336 <span class="comment">/* Note that the variable "name" field omits the prefix common to the</span>
00337 <span class="comment"> whole registration, hence the strange comparison here. */</span>
00338
00339 rc = <a class="code" href="group__library.html#ga103">snmp_oid_compare</a>(vp->name, vp->namelen,
00340 name + current->namelen,
00341 name_len - current->namelen);
00342
00343 <span class="keywordflow">if</span> (name_len - current->namelen > vp->namelen) {
00344 common_len = vp->namelen;
00345 } <span class="keywordflow">else</span> {
00346 common_len = name_len - current->namelen;
00347 }
00348
00349 rc2 = <a class="code" href="group__library.html#ga103">snmp_oid_compare</a>(vp->name, common_len,
00350 name + current->namelen, common_len);
00351
00352 <span class="keywordflow">if</span> (rc >= 0) {
00353 <span class="keywordflow">break</span>; <span class=
"comment">/* All following variables belong to the second subtree */</span>
00354 }
00355
00356 current->variables_len++;
00357 <span class="keywordflow">if</span> (rc2 < 0) {
00358 new_sub->variables_len--;
00359 cp = (<span class="keywordtype">char</span> *) new_sub->variables;
00360 new_sub->variables = (<span class="keyword">struct </span>variable *)(cp +
00361 new_sub->variables_width);
00362 }
00363 vp = (<span class="keyword">struct </span>variable *) ((<span class=
"keywordtype">char</span> *) vp + current->variables_width);
00364 }
00365
00366 <span class="comment">/* Delegated trees should retain their variables regardless */</span>
00367 <span class="keywordflow">if</span> (current->variables_len > 0 &&
00368 IS_DELEGATED((u_char) current->variables[0].type)) {
00369 new_sub->variables_len = 1;
00370 new_sub->variables = current->variables;
00371 }
00372
00373 <span class="comment">/* Propogate this split down through any children */</span>
00374 <span class="keywordflow">if</span> (current->children) {
00375 new_sub->children = netsnmp_subtree_split(current->children,
00376 name, name_len);
00377 }
00378
00379 <span class="comment">/* Retain the correct linking of the list */</span>
00380 <span class="keywordflow">for</span> (ptr = current; ptr != NULL; ptr = ptr->children) {
00381 netsnmp_subtree_change_next(ptr, new_sub);
00382 }
00383 <span class="keywordflow">for</span> (ptr = new_sub; ptr != NULL; ptr = ptr->children) {
00384 netsnmp_subtree_change_prev(ptr, current);
00385 }
00386 <span class="keywordflow">for</span> (ptr = new_sub->next; ptr != NULL; ptr=ptr->children) {
00387 netsnmp_subtree_change_prev(ptr, new_sub);
00388 }
00389
00390 <span class="keywordflow">return</span> new_sub;
00391 }
00392
00393 <span class="keywordtype">int</span>
00394 netsnmp_subtree_load(netsnmp_subtree *new_sub, <span class="keyword">const</span> <span class=
"keywordtype">char</span> *context_name)
00395 {
00396 netsnmp_subtree *tree1, *tree2, *new2;
00397 netsnmp_subtree *prev, *next;
00398 <span class="keywordtype">int</span> res, rc = 0;
00399
00400 <span class="keywordflow">if</span> (new_sub == NULL) {
00401 <span class="keywordflow">return</span> MIB_REGISTERED_OK; <span class="comment">/* Degenerate case */</span>
00402 }
00403
00404 <span class="keywordflow">if</span> (!netsnmp_subtree_find_first(context_name)) {
00405 <span class="keyword">static</span> <span class="keywordtype">int</span> inloop = 0;
00406 <span class="keywordflow">if</span> (!inloop) {
00407 oid ccitt[1] = { 0 };
00408 oid iso[1] = { 1 };
00409 oid joint_ccitt_iso[1] = { 2 };
00410 inloop = 1;
00411 netsnmp_register_null_context(snmp_duplicate_objid(ccitt, 1), 1,
00412 context_name);
00413 netsnmp_register_null_context(snmp_duplicate_objid(iso, 1), 1,
00414 context_name);
00415 netsnmp_register_null_context(snmp_duplicate_objid(joint_ccitt_iso, 1),
00416 1, context_name);
00417 inloop = 0;
00418 }
00419 }
00420
00421 <span class="comment">/* Find the subtree that contains the start of the new subtree (if</span>
00422 <span class="comment"> any)...*/</span>
00423
00424 tree1 = netsnmp_subtree_find(new_sub->start_a, new_sub->start_len,
00425 NULL, context_name);
00426
00427 <span class="comment">/* ... and the subtree that follows the new one (NULL implies this is the</span>
00428 <span class="comment"> final region covered). */</span>
00429
00430 <span class="keywordflow">if</span> (tree1 == NULL) {
00431 tree2 = netsnmp_subtree_find_next(new_sub->start_a, new_sub->start_len,
00432 NULL, context_name);
00433 } <span class="keywordflow">else</span> {
00434 tree2 = tree1->next;
00435 }
00436
00437 <span class="comment">/* Handle new subtrees that start in virgin territory. */</span>
00438
00439 <span class="keywordflow">if</span> (tree1 == NULL) {
00440 new2 = NULL;
00441 <span class="comment">/* Is there any overlap with later subtrees? */</span>
00442 <span class="keywordflow">if</span> (tree2 && <a class="code" href=
"group__library.html#ga103">snmp_oid_compare</a>(new_sub->end_a, new_sub->end_len,
00443 tree2->start_a, tree2->start_len) > 0) {
00444 new2 = netsnmp_subtree_split(new_sub,
00445 tree2->start_a, tree2->start_len);
00446 }
00447
00448 <span class="comment">/* Link the new subtree (less any overlapping region) with the list of</span>
00449 <span class="comment"> existing registrations. */</span>
00450
00451 <span class="keywordflow">if</span> (tree2) {
00452 netsnmp_subtree_change_prev(new_sub, tree2->prev);
00453 netsnmp_subtree_change_prev(tree2, new_sub);
00454 } <span class="keywordflow">else</span> {
00455 netsnmp_subtree_change_prev(new_sub,
00456 netsnmp_subtree_find_prev(new_sub->start_a,
00457 new_sub->start_len, NULL, context_name));
00458
00459 <span class="keywordflow">if</span> (new_sub->prev) {
00460 netsnmp_subtree_change_next(new_sub->prev, new_sub);
00461 } <span class="keywordflow">else</span> {
00462 netsnmp_subtree_replace_first(new_sub, context_name);
00463 }
00464
00465 netsnmp_subtree_change_next(new_sub, tree2);
00466
00467 <span class="comment">/* If there was any overlap, recurse to merge in the overlapping</span>
00468 <span class="comment"> region (including anything that may follow the overlap). */</span>
00469 <span class="keywordflow">if</span> (new2) {
00470 <span class="keywordflow">return</span> netsnmp_subtree_load(new2, context_name);
00471 }
00472 }
00473 } <span class="keywordflow">else</span> {
00474 <span class="comment">/* If the new subtree starts *within* an existing registration</span>
00475 <span class="comment"> (rather than at the same point as it), then split the existing</span>
00476 <span class="comment"> subtree at this point. */</span>
00477
00478 <span class="keywordflow">if</span> (<a class="code" href=
"group__library.html#ga106">netsnmp_oid_equals</a>(new_sub->start_a, new_sub->start_len,
00479 tree1->start_a, tree1->start_len) != 0) {
00480 tree1 = netsnmp_subtree_split(tree1, new_sub->start_a,
00481 new_sub->start_len);
00482 }
00483
00484 <span class="keywordflow">if</span> (tree1 == NULL) {
00485 <span class="keywordflow">return</span> MIB_REGISTRATION_FAILED;
00486 }
00487
00488 <span class="comment">/* Now consider the end of this existing subtree:</span>
00489 <span class="comment"> </span>
00490 <span class="comment"> If it matches the new subtree precisely,</span>
00491 <span class="comment"> simply merge the new one into the list of children</span>
00492
00493 <span class="comment"> If it includes the whole of the new subtree,</span>
00494 <span class="comment"> split it at the appropriate point, and merge again</span>
00495 <span class="comment"> </span>
00496 <span class="comment"> If the new subtree extends beyond this existing region,</span>
00497 <span class="comment"> split it, and recurse to merge the two parts. */</span>
00498
00499 rc = <a class="code" href="group__library.html#ga103">snmp_oid_compare</a>(new_sub->end_a, new_sub->end_len,
00500 tree1->end_a, tree1->end_len);
00501
00502 <span class="keywordflow">switch</span> (rc) {
00503
00504 <span class="keywordflow">case</span> -1:
00505 <span class="comment">/* Existing subtree contains new one. */</span>
00506 netsnmp_subtree_split(tree1, new_sub->end_a, new_sub->end_len);
00507 <span class="comment">/* Fall Through */</span>
00508
00509 <span class="keywordflow">case</span> 0:
00510 <span class="comment">/* The two trees match precisely. */</span>
00511
00512 <span class="comment">/* Note: This is the only point where the original registration</span>
00513 <span class="comment"> OID ("name") is used. */</span>
00514
00515 prev = NULL;
00516 next = tree1;
00517
00518 <span class="keywordflow">while</span> (next && next->namelen > new_sub->namelen) {
00519 prev = next;
00520 next = next->children;
00521 }
00522
00523 <span class="keywordflow">while</span> (next && next->namelen == new_sub->namelen &&
00524 next->priority < new_sub->priority ) {
00525 prev = next;
00526 next = next->children;
00527 }
00528
00529 <span class="keywordflow">if</span> (next && (next->namelen == new_sub->namelen) &&
00530 (next->priority == new_sub->priority)) {
00531 netsnmp_assert(<span class="stringliteral">"registration"</span> != <span class=
"stringliteral">"duplicate"</span>);
00532 <span class="keywordflow">return</span> MIB_DUPLICATE_REGISTRATION;
00533 }
00534
00535 <span class="keywordflow">if</span> (prev) {
00536 prev->children = new_sub;
00537 new_sub->children = next;
00538 netsnmp_subtree_change_prev(new_sub, prev->prev);
00539 netsnmp_subtree_change_next(new_sub, prev->next);
00540 } <span class="keywordflow">else</span> {
00541 new_sub->children = next;
00542 netsnmp_subtree_change_prev(new_sub, next->prev);
00543 netsnmp_subtree_change_next(new_sub, next->next);
00544
00545 <span class="keywordflow">for</span> (next = new_sub->next; next != NULL;next = next->children){
00546 netsnmp_subtree_change_prev(next, new_sub);
00547 }
00548
00549 <span class="keywordflow">for</span> (prev = new_sub->prev; prev != NULL;prev = prev->children){
00550 netsnmp_subtree_change_next(prev, new_sub);
00551 }
00552 }
00553 <span class="keywordflow">break</span>;
00554
00555 <span class="keywordflow">case</span> 1:
00556 <span class="comment">/* New subtree contains the existing one. */</span>
00557 new2 = netsnmp_subtree_split(new_sub, tree1->end_a,tree1->end_len);
00558 res = netsnmp_subtree_load(new_sub, context_name);
00559 <span class="keywordflow">if</span> (res != MIB_REGISTERED_OK) {
00560 netsnmp_subtree_free(new2);
00561 <span class="keywordflow">return</span> res;
00562 }
00563 <span class="keywordflow">return</span> netsnmp_subtree_load(new2, context_name);
00564 }
00565 }
00566 <span class="keywordflow">return</span> 0;
00567 }
00568
00569 <span class="comment">/*</span>
00570 <span class="comment"> * Note: reginfo will be freed on failures</span>
00571 <span class="comment"> */</span>
00572 <span class="keywordtype">int</span>
00573 netsnmp_register_mib(<span class="keyword">const</span> <span class="keywordtype">char</span> *moduleName,
00574 <span class="keyword">struct</span> variable *var,
00575 size_t varsize,
00576 size_t numvars,
00577 oid * mibloc,
00578 size_t mibloclen,
00579 <span class="keywordtype">int</span> priority,
00580 <span class="keywordtype">int</span> range_subid,
00581 oid range_ubound,
00582 <a class="code" href="structsnmp__session.html">netsnmp_session</a> * ss,
00583 <span class="keyword">const</span> <span class="keywordtype">char</span> *context,
00584 <span class="keywordtype">int</span> timeout,
00585 <span class="keywordtype">int</span> flags,
00586 <a class="code" href=
"structnetsnmp__handler__registration__s.html">netsnmp_handler_registration</a> *reginfo,
00587 <span class="keywordtype">int</span> perform_callback)
00588 {
00589 netsnmp_subtree *subtree, *sub2;
00590 <span class="keywordtype">int</span> res, i;
00591 <span class="keyword">struct </span>register_parameters reg_parms;
00592 <span class="keywordtype">int</span> old_lookup_cache_val = <a class="code" href=
"group__agent__registry.html#ga10">netsnmp_get_lookup_cache_size</a>();
00593
00594 <span class="keywordflow">if</span> (moduleName == NULL ||
00595 mibloc == NULL) {
00596 <span class="comment">/* Shouldn't happen ??? */</span>
00597 <a class="code" href="group__handler.html#ga21">netsnmp_handler_registration_free</a>(reginfo);
00598 <span class="keywordflow">return</span> MIB_REGISTRATION_FAILED;
00599 }
00600 subtree = (netsnmp_subtree *)calloc(1, <span class="keyword">sizeof</span>(netsnmp_subtree));
00601 <span class="keywordflow">if</span> (subtree == NULL) {
00602 <a class="code" href="group__handler.html#ga21">netsnmp_handler_registration_free</a>(reginfo);
00603 <span class="keywordflow">return</span> MIB_REGISTRATION_FAILED;
00604 }
00605
00606 DEBUGMSGTL((<span class="stringliteral">"register_mib"</span>, <span class=
"stringliteral">"registering \"%s\" at "</span>, moduleName));
00607 DEBUGMSGOIDRANGE((<span class="stringliteral">"register_mib"</span>, mibloc, mibloclen, range_subid,
00608 range_ubound));
00609 DEBUGMSG((<span class="stringliteral">"register_mib"</span>, <span class=
"stringliteral">" with context \"%s\"\n"</span>, context));
00610
00611 <span class="comment">/*</span>
00612 <span class="comment"> * verify that the passed context is equal to the context</span>
00613 <span class="comment"> * in the reginfo.</span>
00614 <span class="comment"> * (which begs the question, why do we have both? It appears that the</span>
00615 <span class="comment"> * reginfo item didn't appear til 5.2)</span>
00616 <span class="comment"> */</span>
00617 <span class="keywordflow">if</span>( ((NULL == context) && (NULL != reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a>)) ||
00618 ((NULL != context) && (NULL == reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a>)) ||
00619 ( ((NULL != context) && (NULL != reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a>)) &&
00620 (0 != strcmp(context, reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a>))) ) {
00621 <a class="code" href="group__snmp__logging.html#ga41">snmp_log</a>(LOG_WARNING,<span class=
"stringliteral">"context passed during registration does not "</span>
00622 <span class="stringliteral">"equal the reginfo contextName! ('%s' != '%s')\n"</span>,
00623 context, reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a>);
00624 netsnmp_assert(<span class="stringliteral">"register context"</span> == <span class=
"stringliteral">"reginfo->contextName"</span>);
00625 }
00626
00627 <span class="comment">/* Create the new subtree node being registered. */</span>
00628
00629 subtree->reginfo = reginfo;
00630 subtree->name_a = snmp_duplicate_objid(mibloc, mibloclen);
00631 subtree->start_a = snmp_duplicate_objid(mibloc, mibloclen);
00632 subtree->end_a = snmp_duplicate_objid(mibloc, mibloclen);
00633 subtree->label_a = strdup(moduleName);
00634 <span class="keywordflow">if</span> (subtree->name_a == NULL || subtree->start_a == NULL ||
00635 subtree->end_a == NULL || subtree->label_a == NULL) {
00636 netsnmp_subtree_free(subtree); <span class="comment">/* also frees reginfo */</span>
00637 <span class="keywordflow">return</span> MIB_REGISTRATION_FAILED;
00638 }
00639 subtree->namelen = (u_char)mibloclen;
00640 subtree->start_len = (u_char)mibloclen;
00641 subtree->end_len = (u_char)mibloclen;
00642 subtree->end_a[mibloclen - 1]++;
00643
00644 <span class="keywordflow">if</span> (var != NULL) {
00645 subtree->variables = (<span class="keyword">struct </span>variable *)malloc(varsize*numvars);
00646 <span class="keywordflow">if</span> (subtree->variables == NULL) {
00647 netsnmp_subtree_free(subtree); <span class="comment">/* also frees reginfo */</span>
00648 <span class="keywordflow">return</span> MIB_REGISTRATION_FAILED;
00649 }
00650 memcpy(subtree->variables, var, numvars*varsize);
00651 subtree->variables_len = numvars;
00652 subtree->variables_width = varsize;
00653 }
00654 subtree-><a class="code" href="structnetsnmp__handler__registration__s.html#o6">priority</a> = priority;
00655 subtree-><a class="code" href="structnetsnmp__handler__registration__s.html#o9">timeout</a> = timeout;
00656 subtree-><a class="code" href="structnetsnmp__handler__registration__s.html#o7">range_subid</a> = range_subid;
00657 subtree-><a class="code" href="structnetsnmp__handler__registration__s.html#o8">range_ubound</a> = range_ubound;
00658 subtree->session = ss;
00659 subtree-><a class="code" href="structsnmp__session.html#o3">flags</a> = (u_char)flags; <span class=
"comment">/* used to identify instance oids */</span>
00660 subtree-><a class="code" href="structsnmp__session.html#o3">flags</a> |= SUBTREE_ATTACHED;
00661 subtree->global_cacheid = reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o10">global_cacheid</a>;
00662
00663 <a class="code" href="group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(0);
00664 res = netsnmp_subtree_load(subtree, context);
00665
00666 <span class="comment">/* If registering a range, use the first subtree as a template for the</span>
00667 <span class="comment"> rest of the range. */</span>
00668
00669 <span class="keywordflow">if</span> (res == MIB_REGISTERED_OK && range_subid != 0) {
00670 <span class="keywordflow">for</span> (i = mibloc[range_subid - 1] + 1; i <= (int)range_ubound; i++) {
00671 sub2 = netsnmp_subtree_deepcopy(subtree);
00672
00673 <span class="keywordflow">if</span> (sub2 == NULL) {
00674 <a class="code" href=
"group__agent__registry.html#ga32">unregister_mib_context</a>(mibloc, mibloclen, priority,
00675 range_subid, range_ubound, context);
00676 <a class="code" href=
"group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(old_lookup_cache_val);
00677 invalidate_lookup_cache(context);
00678 <span class="keywordflow">return</span> MIB_REGISTRATION_FAILED;
00679 }
00680
00681 sub2->name_a[range_subid - 1] = i;
00682 sub2->start_a[range_subid - 1] = i;
00683 sub2->end_a[range_subid - 1] = i; <span class="comment">/* XXX - ???? */</span>
00684 <span class="keywordflow">if</span> (range_subid == (int)mibloclen)
00685 ++sub2->end_a[range_subid - 1];
00686 res = netsnmp_subtree_load(sub2, context);
00687 sub2->flags |= SUBTREE_ATTACHED;
00688 <span class="keywordflow">if</span> (res != MIB_REGISTERED_OK) {
00689 <a class="code" href=
"group__agent__registry.html#ga32">unregister_mib_context</a>(mibloc, mibloclen, priority,
00690 range_subid, range_ubound, context);
00691 netsnmp_subtree_free(sub2);
00692 <a class="code" href=
"group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(old_lookup_cache_val);
00693 invalidate_lookup_cache(context);
00694 <span class="keywordflow">return</span> res;
00695 }
00696 }
00697 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (res == MIB_DUPLICATE_REGISTRATION ||
00698 res == MIB_REGISTRATION_FAILED) {
00699 <a class="code" href="group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(old_lookup_cache_val);
00700 invalidate_lookup_cache(context);
00701 netsnmp_subtree_free(subtree);
00702 <span class="keywordflow">return</span> res;
00703 }
00704
00705 <span class="comment">/*</span>
00706 <span class="comment"> * mark the MIB as detached, if there's no master agent present as of now </span>
00707 <span class="comment"> */</span>
00708 <span class="keywordflow">if</span> (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00709 NETSNMP_DS_AGENT_ROLE) != MASTER_AGENT) {
00710 <span class="keyword">extern</span> <span class="keyword">struct </span><a class="code" href=
"structsnmp__session.html">snmp_session</a> *main_session;
00711 <span class="keywordflow">if</span> (main_session == NULL) {
00712 register_mib_detach_node(subtree);
00713 }
00714 }
00715
00716 <span class="keywordflow">if</span> (res == MIB_REGISTERED_OK && perform_callback) {
00717 memset(&reg_parms, 0x0, <span class="keyword">sizeof</span>(reg_parms));
00718 reg_parms.name = mibloc;
00719 reg_parms.namelen = mibloclen;
00720 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o6">priority</a> = priority;
00721 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o7">range_subid</a> = range_subid;
00722 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o8">range_ubound</a> = range_ubound;
00723 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o9">timeout</a> = timeout;
00724 reg_parms.flags = (u_char) flags;
00725 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o1">contextName</a> = context;
00726 <a class="code" href="group__callback.html#ga10">snmp_call_callbacks</a>(SNMP_CALLBACK_APPLICATION,
00727 SNMPD_CALLBACK_REGISTER_OID, &reg_parms);
00728 }
00729
00730 <a class="code" href="group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(old_lookup_cache_val);
00731 invalidate_lookup_cache(context);
00732 <span class="keywordflow">return</span> res;
00733 }
00734
00735 <span class="comment">/*</span>
00736 <span class="comment"> * Reattach a particular node. </span>
00737 <span class="comment"> */</span>
00738
00739 <span class="keyword">static</span> <span class="keywordtype">void</span>
00740 register_mib_reattach_node(netsnmp_subtree *s)
00741 {
00742 <span class=
"keywordflow">if</span> ((s != NULL) && (s->namelen > 1) && !(s->flags & SUBTREE_ATTACHED)) {
00743 <span class="keyword">struct </span>register_parameters reg_parms;
00744 <span class="comment">/*</span>
00745 <span class="comment"> * only do registrations that are not the top level nodes </span>
00746 <span class="comment"> */</span>
00747 memset(&reg_parms, 0x0, <span class="keyword">sizeof</span>(reg_parms));
00748
00749 <span class="comment">/*</span>
00750 <span class="comment"> * XXX: do this better </span>
00751 <span class="comment"> */</span>
00752 reg_parms.name = s->name_a;
00753 reg_parms.namelen = s->namelen;
00754 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o6">priority</a> = s-><a class=
"code" href="structnetsnmp__handler__registration__s.html#o6">priority</a>;
00755 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o7">range_subid</a> = s-><a class=
"code" href="structnetsnmp__handler__registration__s.html#o7">range_subid</a>;
00756 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o8">range_ubound</a> = s-><a class=
"code" href="structnetsnmp__handler__registration__s.html#o8">range_ubound</a>;
00757 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o9">timeout</a> = s-><a class=
"code" href="structnetsnmp__handler__registration__s.html#o9">timeout</a>;
00758 reg_parms.flags = s->flags;
00759 <span class="keywordflow">if</span> ((NULL != s->reginfo) && (NULL != s->reginfo->contextName))
00760 reg_parms.<a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a> = s->reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a>;
00761 <a class="code" href="group__callback.html#ga10">snmp_call_callbacks</a>(SNMP_CALLBACK_APPLICATION,
00762 SNMPD_CALLBACK_REGISTER_OID, &reg_parms);
00763 s->flags |= SUBTREE_ATTACHED;
00764 }
00765 }
00766
00767 <span class="comment">/*</span>
00768 <span class="comment"> * Call callbacks to reattach all our nodes. </span>
00769 <span class="comment"> */</span>
00770
00771 <span class="keywordtype">void</span>
00772 register_mib_reattach(<span class="keywordtype">void</span>)
00773 {
00774 netsnmp_subtree *s, *t;
00775 subtree_context_cache *ptr;
00776
00777 <span class="keywordflow">for</span> (ptr = context_subtrees; ptr; ptr = ptr->next) {
00778 <span class="keywordflow">for</span> (s = ptr->first_subtree; s != NULL; s = s->next) {
00779 register_mib_reattach_node(s);
00780 <span class="keywordflow">for</span> (t = s->children; t != NULL; t = t->children) {
00781 register_mib_reattach_node(t);
00782 }
00783 }
00784 }
00785 }
00786
00787 <span class="comment">/*</span>
00788 <span class="comment"> * Mark a node as detached. </span>
00789 <span class="comment"> */</span>
00790
00791 <span class="keyword">static</span> <span class="keywordtype">void</span>
00792 register_mib_detach_node(netsnmp_subtree *s)
00793 {
00794 <span class="keywordflow">if</span> (s != NULL) {
00795 s->flags = s->flags & ~SUBTREE_ATTACHED;
00796 }
00797 }
00798
00799 <span class="comment">/*</span>
00800 <span class="comment"> * Mark all our registered OIDs as detached. This is only really</span>
00801 <span class="comment"> * useful for subagent protocols, when a connection is lost or</span>
00802 <span class="comment"> * something. </span>
00803 <span class="comment"> */</span>
00804
00805 <span class="keywordtype">void</span>
00806 register_mib_detach(<span class="keywordtype">void</span>)
00807 {
00808 netsnmp_subtree *s, *t;
00809 subtree_context_cache *ptr;
00810 <span class="keywordflow">for</span> (ptr = context_subtrees; ptr; ptr = ptr->next) {
00811 <span class="keywordflow">for</span> (s = ptr->first_subtree; s != NULL; s = s->next) {
00812 register_mib_detach_node(s);
00813 <span class="keywordflow">for</span> (t = s->children; t != NULL; t = t->children) {
00814 register_mib_detach_node(t);
00815 }
00816 }
00817 }
00818 }
00819
00820 <span class="keywordtype">int</span>
00821 register_mib_context(<span class="keyword">const</span> <span class="keywordtype">char</span> *moduleName,
00822 <span class="keyword">struct</span> variable *var,
00823 size_t varsize,
00824 size_t numvars,
00825 oid * mibloc,
00826 size_t mibloclen,
00827 <span class="keywordtype">int</span> priority,
00828 <span class="keywordtype">int</span> range_subid,
00829 oid range_ubound,
00830 <a class="code" href="structsnmp__session.html">netsnmp_session</a> * ss,
00831 <span class="keyword">const</span> <span class="keywordtype">char</span> *context, <span class=
"keywordtype">int</span> timeout, <span class="keywordtype">int</span> flags)
00832 {
00833 <span class="keywordflow">return</span> <a class="code" href=
"group__old__api.html#ga1">netsnmp_register_old_api</a>(moduleName, var, varsize, numvars,
00834 mibloc, mibloclen, priority,
00835 range_subid, range_ubound, ss, context,
00836 timeout, flags);
00837 }
00838
00839 <span class="keywordtype">int</span>
00840 register_mib_range(<span class="keyword">const</span> <span class="keywordtype">char</span> *moduleName,
00841 <span class="keyword">struct</span> variable *var,
00842 size_t varsize,
00843 size_t numvars,
00844 oid * mibloc,
00845 size_t mibloclen,
00846 <span class="keywordtype">int</span> priority,
00847 <span class="keywordtype">int</span> range_subid, oid range_ubound, <a class="code" href=
"structsnmp__session.html">netsnmp_session</a> * ss)
00848 {
00849 <span class="keywordflow">return</span> register_mib_context(moduleName, var, varsize, numvars,
00850 mibloc, mibloclen, priority,
00851 range_subid, range_ubound, ss, <span class="stringliteral">""</span>, -1, 0);
00852 }
00853
00854 <span class="keywordtype">int</span>
00855 register_mib_priority(<span class="keyword">const</span> <span class="keywordtype">char</span> *moduleName,
00856 <span class="keyword">struct</span> variable *var,
00857 size_t varsize,
00858 size_t numvars,
00859 oid * mibloc, size_t mibloclen, <span class="keywordtype">int</span> priority)
00860 {
00861 <span class="keywordflow">return</span> register_mib_range(moduleName, var, varsize, numvars,
00862 mibloc, mibloclen, priority, 0, 0, NULL);
00863 }
00864
00865 <span class="keywordtype">int</span>
00866 register_mib(<span class="keyword">const</span> <span class="keywordtype">char</span> *moduleName,
00867 <span class="keyword">struct</span> variable *var,
00868 size_t varsize,
00869 size_t numvars, oid * mibloc, size_t mibloclen)
00870 {
00871 <span class="keywordflow">return</span> register_mib_priority(moduleName, var, varsize, numvars,
00872 mibloc, mibloclen, DEFAULT_MIB_PRIORITY);
00873 }
00874
00875 <span class="keywordtype">void</span>
00876 netsnmp_subtree_unload(netsnmp_subtree *sub, netsnmp_subtree *prev, <span class="keyword">const</span> <span class=
"keywordtype">char</span> *context)
00877 {
00878 netsnmp_subtree *ptr;
00879
00880 DEBUGMSGTL((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">"unload("</span>));
00881 <span class="keywordflow">if</span> (sub != NULL) {
00882 DEBUGMSGOID((<span class="stringliteral">"register_mib"</span>, sub->start_a, sub->start_len));
00883 } <span class="keywordflow">else</span> {
00884 DEBUGMSG((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">"[NIL]"</span>));
00885 }
00886 DEBUGMSG((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">", "</span>));
00887 <span class="keywordflow">if</span> (prev != NULL) {
00888 DEBUGMSGOID((<span class="stringliteral">"register_mib"</span>, prev->start_a, prev->start_len));
00889 } <span class="keywordflow">else</span> {
00890 DEBUGMSG((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">"[NIL]"</span>));
00891 }
00892 DEBUGMSG((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">")\n"</span>));
00893
00894 <span class="keywordflow">if</span> (prev != NULL) { <span class=
"comment">/* non-leading entries are easy */</span>
00895 prev->children = sub->children;
00896 invalidate_lookup_cache(context);
00897 <span class="keywordflow">return</span>;
00898 }
00899 <span class="comment">/*</span>
00900 <span class="comment"> * otherwise, we need to amend our neighbours as well </span>
00901 <span class="comment"> */</span>
00902
00903 <span class="keywordflow">if</span> (sub->children == NULL) { <span class=
"comment">/* just remove this node completely */</span>
00904 <span class="keywordflow">for</span> (ptr = sub->prev; ptr; ptr = ptr->children) {
00905 netsnmp_subtree_change_next(ptr, sub->next);
00906 }
00907 <span class="keywordflow">for</span> (ptr = sub->next; ptr; ptr = ptr->children) {
00908 netsnmp_subtree_change_prev(ptr, sub->prev);
00909 }
00910
00911 <span class="keywordflow">if</span> (sub->prev == NULL) {
00912 netsnmp_subtree_replace_first(sub->next, context);
00913 }
00914
00915 } <span class="keywordflow">else</span> {
00916 <span class="keywordflow">for</span> (ptr = sub->prev; ptr; ptr = ptr->children)
00917 netsnmp_subtree_change_next(ptr, sub->children);
00918 <span class="keywordflow">for</span> (ptr = sub->next; ptr; ptr = ptr->children)
00919 netsnmp_subtree_change_prev(ptr, sub->children);
00920
00921 <span class="keywordflow">if</span> (sub->prev == NULL) {
00922 netsnmp_subtree_replace_first(sub->children, context);
00923 }
00924 }
00925 invalidate_lookup_cache(context);
00926 }
00927
00957 <span class="keywordtype">int</span>
<a name="l00958" id="l00958"></a><a class="code" href="group__agent__registry.html#ga32">00958</a> <a class="code" href=
"group__agent__registry.html#ga32">unregister_mib_context</a>(oid * name, size_t len, <span class=
"keywordtype">int</span> priority,
00959 <span class="keywordtype">int</span> range_subid, oid range_ubound,
00960 <span class="keyword">const</span> <span class="keywordtype">char</span> *context)
00961 {
00962 netsnmp_subtree *list, *myptr;
00963 netsnmp_subtree *prev, *child, *next; <span class="comment">/* loop through children */</span>
00964 <span class="keyword">struct </span>register_parameters reg_parms;
00965 <span class="keywordtype">int</span> old_lookup_cache_val = <a class="code" href=
"group__agent__registry.html#ga10">netsnmp_get_lookup_cache_size</a>();
00966 <a class="code" href="group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(0);
00967
00968 DEBUGMSGTL((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">"unregistering "</span>));
00969 DEBUGMSGOIDRANGE((<span class="stringliteral">"register_mib"</span>, name, len, range_subid, range_ubound));
00970 DEBUGMSG((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">"\n"</span>));
00971
00972 list = netsnmp_subtree_find(name, len, netsnmp_subtree_find_first(context),
00973 context);
00974 <span class="keywordflow">if</span> (list == NULL) {
00975 <span class="keywordflow">return</span> MIB_NO_SUCH_REGISTRATION;
00976 }
00977
00978 <span class="keywordflow">for</span> (child = list, prev = NULL; child != NULL;
00979 prev = child, child = child->children) {
00980 <span class="keywordflow">if</span> (<a class="code" href=
"group__library.html#ga106">netsnmp_oid_equals</a>(child->name_a, child->namelen, name, len) == 0 &&
00981 child->priority == priority) {
00982 <span class="keywordflow">break</span>; <span class="comment">/* found it */</span>
00983 }
00984 }
00985
00986 <span class="keywordflow">if</span> (child == NULL) {
00987 <span class="keywordflow">return</span> MIB_NO_SUCH_REGISTRATION;
00988 }
00989
00990 netsnmp_subtree_unload(child, prev, context);
00991 myptr = child; <span class="comment">/* remember this for later */</span>
00992
00993 <span class="comment">/*</span>
00994 <span class="comment"> * Now handle any occurances in the following subtrees,</span>
00995 <span class="comment"> * as a result of splitting this range. Due to the</span>
00996 <span class="comment"> * nature of the way such splits work, the first</span>
00997 <span class="comment"> * subtree 'slice' that doesn't refer to the given</span>
00998 <span class="comment"> * name marks the end of the original region.</span>
00999 <span class="comment"> *</span>
01000 <span class="comment"> * This should also serve to register ranges.</span>
01001 <span class="comment"> */</span>
01002
01003 <span class="keywordflow">for</span> (list = myptr->next; list != NULL; list = next) {
01004 next = list->next; <span class="comment">/* list gets freed sometimes; cache next */</span>
01005 <span class="keywordflow">for</span> (child = list, prev = NULL; child != NULL;
01006 prev = child, child = child->children) {
01007 <span class="keywordflow">if</span> ((<a class="code" href=
"group__library.html#ga106">netsnmp_oid_equals</a>(child->name_a, child->namelen,
01008 name, len) == 0) &&
01009 (child->priority == priority)) {
01010 netsnmp_subtree_unload(child, prev, context);
01011 netsnmp_subtree_free(child);
01012 <span class="keywordflow">break</span>;
01013 }
01014 }
01015 <span class="keywordflow">if</span> (child == NULL) <span class=
"comment">/* Didn't find the given name */</span>
01016 <span class="keywordflow">break</span>;
01017 }
01018 netsnmp_subtree_free(myptr);
01019
01020 memset(&reg_parms, 0x0, <span class="keyword">sizeof</span>(reg_parms));
01021 reg_parms.name = name;
01022 reg_parms.namelen = len;
01023 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o6">priority</a> = priority;
01024 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o7">range_subid</a> = range_subid;
01025 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o8">range_ubound</a> = range_ubound;
01026 reg_parms.flags = 0x00; <span class="comment">/* this is okay I think */</span>
01027 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o1">contextName</a> = context;
01028 <a class="code" href="group__callback.html#ga10">snmp_call_callbacks</a>(SNMP_CALLBACK_APPLICATION,
01029 SNMPD_CALLBACK_UNREGISTER_OID, &reg_parms);
01030
01031 <a class="code" href="group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(old_lookup_cache_val);
01032 invalidate_lookup_cache(context);
01033 <span class="keywordflow">return</span> MIB_UNREGISTERED_OK;
01034 }
01035
01036 <span class="keywordtype">int</span>
01037 netsnmp_unregister_mib_table_row(oid * name, size_t len, <span class="keywordtype">int</span> priority,
01038 <span class="keywordtype">int</span> var_subid, oid range_ubound,
01039 <span class="keyword">const</span> <span class="keywordtype">char</span> *context)
01040 {
01041 netsnmp_subtree *list, *myptr;
01042 netsnmp_subtree *prev, *child; <span class="comment">/* loop through children */</span>
01043 <span class="keyword">struct </span>register_parameters reg_parms;
01044 oid range_lbound = name[var_subid - 1];
01045
01046 DEBUGMSGTL((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">"unregistering "</span>));
01047 DEBUGMSGOIDRANGE((<span class="stringliteral">"register_mib"</span>, name, len, var_subid, range_ubound));
01048 DEBUGMSG((<span class="stringliteral">"register_mib"</span>, <span class="stringliteral">"\n"</span>));
01049
01050 <span class="keywordflow">for</span> (; name[var_subid - 1] <= range_ubound; name[var_subid - 1]++) {
01051 list = netsnmp_subtree_find(name, len,
01052 netsnmp_subtree_find_first(context), context);
01053
01054 <span class="keywordflow">if</span> (list == NULL) {
01055 <span class="keywordflow">continue</span>;
01056 }
01057
01058 <span class="keywordflow">for</span> (child = list, prev = NULL; child != NULL;
01059 prev = child, child = child->children) {
01060
01061 <span class="keywordflow">if</span> (<a class="code" href=
"group__library.html#ga106">netsnmp_oid_equals</a>(child->name_a, child->namelen,
01062 name, len) == 0 &&
01063 (child->priority == priority)) {
01064 <span class="keywordflow">break</span>; <span class="comment">/* found it */</span>
01065 }
01066 }
01067
01068 <span class="keywordflow">if</span> (child == NULL) {
01069 <span class="keywordflow">continue</span>;
01070 }
01071
01072 netsnmp_subtree_unload(child, prev, context);
01073 myptr = child; <span class="comment">/* remember this for later */</span>
01074
01075 <span class="keywordflow">for</span> (list = myptr->next; list != NULL; list = list->next) {
01076 <span class="keywordflow">for</span> (child = list, prev = NULL; child != NULL;
01077 prev = child, child = child->children) {
01078
01079 <span class="keywordflow">if</span> (<a class="code" href=
"group__library.html#ga106">netsnmp_oid_equals</a>(child->name_a, child->namelen,
01080 name, len) == 0 &&
01081 (child->priority == priority)) {
01082 netsnmp_subtree_unload(child, prev, context);
01083 netsnmp_subtree_free(child);
01084 <span class="keywordflow">break</span>;
01085 }
01086 }
01087 <span class="keywordflow">if</span> (child == NULL) { <span class=
"comment">/* Didn't find the given name */</span>
01088 <span class="keywordflow">break</span>;
01089 }
01090 }
01091 netsnmp_subtree_free(myptr);
01092 }
01093
01094 name[var_subid - 1] = range_lbound;
01095 memset(&reg_parms, 0x0, <span class="keyword">sizeof</span>(reg_parms));
01096 reg_parms.name = name;
01097 reg_parms.namelen = len;
01098 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o6">priority</a> = priority;
01099 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o7">range_subid</a> = var_subid;
01100 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o8">range_ubound</a> = range_ubound;
01101 reg_parms.flags = 0x00; <span class="comment">/* this is okay I think */</span>
01102 reg_parms.<a class="code" href="structnetsnmp__handler__registration__s.html#o1">contextName</a> = context;
01103 <a class="code" href="group__callback.html#ga10">snmp_call_callbacks</a>(SNMP_CALLBACK_APPLICATION,
01104 SNMPD_CALLBACK_UNREGISTER_OID, &reg_parms);
01105
01106 <span class="keywordflow">return</span> 0;
01107 }
01108
01109 <span class="keywordtype">int</span>
01110 unregister_mib_range(oid * name, size_t len, <span class="keywordtype">int</span> priority,
01111 <span class="keywordtype">int</span> range_subid, oid range_ubound)
01112 {
01113 <span class="keywordflow">return</span> <a class="code" href=
"group__agent__registry.html#ga32">unregister_mib_context</a>(name, len, priority, range_subid,
01114 range_ubound, <span class="stringliteral">""</span>);
01115 }
01116
01117 <span class="keywordtype">int</span>
01118 unregister_mib_priority(oid * name, size_t len, <span class="keywordtype">int</span> priority)
01119 {
01120 <span class="keywordflow">return</span> unregister_mib_range(name, len, priority, 0, 0);
01121 }
01122
01123 <span class="keywordtype">int</span>
01124 unregister_mib(oid * name, size_t len)
01125 {
01126 <span class="keywordflow">return</span> unregister_mib_priority(name, len, DEFAULT_MIB_PRIORITY);
01127 }
01128
01129 <span class="keywordtype">void</span>
01130 unregister_mibs_by_session(<a class="code" href="structsnmp__session.html">netsnmp_session</a> * ss)
01131 {
01132 netsnmp_subtree *list, *list2;
01133 netsnmp_subtree *child, *prev, *next_child;
01134 <span class="keyword">struct </span>register_parameters rp;
01135 subtree_context_cache *contextptr;
01136
01137 DEBUGMSGTL((<span class="stringliteral">"register_mib"</span>, <span class=
"stringliteral">"unregister_mibs_by_session(%p) ctxt \"%s\"\n"</span>,
01138 ss, (ss && ss-><a class="code" href=
"structsnmp__session.html#o25">contextName</a>) ? ss-><a class="code" href=
"structsnmp__session.html#o25">contextName</a> : <span class="stringliteral">"[NIL]"</span>));
01139
01140 <span class="keywordflow">for</span> (contextptr = get_top_context_cache(); contextptr != NULL;
01141 contextptr = contextptr->next) {
01142 <span class="keywordflow">for</span> (list = contextptr->first_subtree; list != NULL; list = list2) {
01143 list2 = list->next;
01144
01145 <span class="keywordflow">for</span> (child = list, prev = NULL; child != NULL; child = next_child){
01146 next_child = child->children;
01147
01148 <span class="keywordflow">if</span> (((!ss || ss-><a class="code" href=
"structsnmp__session.html#o3">flags</a> & SNMP_FLAGS_SUBSESSION) &&
01149 child->session == ss) ||
01150 (!(!ss || ss-><a class="code" href=
"structsnmp__session.html#o3">flags</a> & SNMP_FLAGS_SUBSESSION) && child->session &&
01151 child->session->subsession == ss)) {
01152
01153 memset(&rp,0x0,<span class="keyword">sizeof</span>(rp));
01154 rp.name = child->name_a;
01155 child->name_a = NULL;
01156 rp.namelen = child->namelen;
01157 rp.<a class="code" href=
"structnetsnmp__handler__registration__s.html#o6">priority</a> = child-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o6">priority</a>;
01158 rp.<a class="code" href=
"structnetsnmp__handler__registration__s.html#o7">range_subid</a> = child-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o7">range_subid</a>;
01159 rp.<a class="code" href=
"structnetsnmp__handler__registration__s.html#o8">range_ubound</a> = child-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o8">range_ubound</a>;
01160 rp.<a class="code" href=
"structnetsnmp__handler__registration__s.html#o9">timeout</a> = child-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o9">timeout</a>;
01161 rp.flags = child->flags;
01162 <span class="keywordflow">if</span> ((NULL != child->reginfo) &&
01163 (NULL != child->reginfo->contextName))
01164 rp.<a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a> = child->reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o1">contextName</a>;
01165
01166 <span class="keywordflow">if</span> (child->reginfo != NULL) {
01167 <span class="comment">/*</span>
01168 <span class="comment"> * Don't let's free the session pointer just yet! </span>
01169 <span class="comment"> */</span>
01170 child->reginfo-><a class="code" href=
"structnetsnmp__handler__registration__s.html#o4">handler</a>-><a class="code" href=
"structnetsnmp__mib__handler__s.html#o1">myvoid</a> = NULL;
01171 <a class="code" href=
"group__handler.html#ga21">netsnmp_handler_registration_free</a>(child->reginfo);
01172 child->reginfo = NULL;
01173 }
01174
01175 netsnmp_subtree_unload(child, prev, contextptr->context_name);
01176 netsnmp_subtree_free(child);
01177
01178 <a class="code" href="group__callback.html#ga10">snmp_call_callbacks</a>(SNMP_CALLBACK_APPLICATION,
01179 SNMPD_CALLBACK_UNREGISTER_OID, &rp);
01180 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(rp.name);
01181 } <span class="keywordflow">else</span> {
01182 prev = child;
01183 }
01184 }
01185 }
01186 netsnmp_subtree_join(contextptr->first_subtree);
01187 }
01188 }
01189
01190 <span class="comment">/*</span>
01191 <span class="comment"> * in_a_view: determines if a given snmp_pdu is allowed to see a</span>
01192 <span class="comment"> * given name/namelen OID pointer</span>
01193 <span class="comment"> * name IN - name of var, OUT - name matched</span>
01194 <span class="comment"> * nameLen IN -number of sub-ids in name, OUT - subid-is in matched name</span>
01195 <span class="comment"> * pi IN - relevant auth info re PDU </span>
01196 <span class="comment"> * cvp IN - relevant auth info re mib module</span>
01197 <span class="comment"> */</span>
01198
01199 <span class="keywordtype">int</span>
01200 in_a_view(oid *name, size_t *namelen, <a class="code" href="structsnmp__pdu.html">netsnmp_pdu</a> *pdu, <span class=
"keywordtype">int</span> type)
01201 {
01202 <span class="keyword">struct </span>view_parameters view_parms;
01203
01204 <span class="keywordflow">if</span> (pdu-><a class="code" href=
"structsnmp__pdu.html#o9">flags</a> & UCD_MSG_FLAG_ALWAYS_IN_VIEW) {
01205 <span class="comment">/* Enable bypassing of view-based access control */</span>
01206 <span class="keywordflow">return</span> VACM_SUCCESS;
01207 }
01208
01209 <span class="comment">/*</span>
01210 <span class="comment"> * check for v1 and counter64s, since snmpv1 doesn't support it </span>
01211 <span class="comment"> */</span>
01212 <span class="preprocessor">#ifndef DISABLE_SNMPV1</span>
01213 <span class="keywordflow">if</span> (pdu-><a class="code" href=
"structsnmp__pdu.html#o0">version</a> == SNMP_VERSION_1 && type == ASN_COUNTER64) {
01214 <span class="keywordflow">return</span> VACM_NOTINVIEW;
01215 }
01216 <span class="preprocessor">#endif</span>
01217
01218 view_parms.pdu = pdu;
01219 view_parms.name = name;
01220 <span class="keywordflow">if</span> (namelen != NULL) {
01221 view_parms.namelen = *namelen;
01222 } <span class="keywordflow">else</span> {
01223 view_parms.namelen = 0;
01224 }
01225 view_parms.errorcode = 0;
01226 view_parms.check_subtree = 0;
01227
01228 <span class="keywordflow">switch</span> (pdu-><a class="code" href="structsnmp__pdu.html#o0">version</a>) {
01229 <span class="preprocessor">#ifndef DISABLE_SNMPV1</span>
01230 <span class="keywordflow">case</span> SNMP_VERSION_1:
01231 <span class="preprocessor">#endif</span>
01232 <span class="preprocessor">#ifndef DISABLE_SNMPV2C</span>
01233 <span class="keywordflow">case</span> SNMP_VERSION_2c:
01234 <span class="preprocessor">#endif</span>
01235 <span class="keywordflow">case</span> SNMP_VERSION_3:
01236 <a class="code" href="group__callback.html#ga10">snmp_call_callbacks</a>(SNMP_CALLBACK_APPLICATION,
01237 SNMPD_CALLBACK_ACM_CHECK, &view_parms);
01238 <span class="keywordflow">return</span> view_parms.errorcode;
01239 }
01240 <span class="keywordflow">return</span> VACM_NOSECNAME;
01241 }
01242
01243 <span class="comment">/*</span>
01244 <span class="comment"> * check_acces: determines if a given snmp_pdu is ever going to be</span>
01245 <span class="comment"> * allowed to do anynthing or if it's not going to ever be</span>
01246 <span class="comment"> * authenticated.</span>
01247 <span class="comment"> */</span>
01248 <span class="keywordtype">int</span>
01249 check_access(<a class="code" href="structsnmp__pdu.html">netsnmp_pdu</a> *pdu)
01250 { <span class="comment">/* IN - pdu being checked */</span>
01251 <span class="keyword">struct </span>view_parameters view_parms;
01252 view_parms.pdu = pdu;
01253 view_parms.name = 0;
01254 view_parms.namelen = 0;
01255 view_parms.errorcode = 0;
01256 view_parms.check_subtree = 0;
01257
01258 <span class="keywordflow">if</span> (pdu-><a class="code" href=
"structsnmp__pdu.html#o9">flags</a> & UCD_MSG_FLAG_ALWAYS_IN_VIEW) {
01259 <span class="comment">/* Enable bypassing of view-based access control */</span>
01260 <span class="keywordflow">return</span> 0;
01261 }
01262
01263 <span class="keywordflow">switch</span> (pdu-><a class="code" href="structsnmp__pdu.html#o0">version</a>) {
01264 <span class="preprocessor">#ifndef DISABLE_SNMPV1</span>
01265 <span class="keywordflow">case</span> SNMP_VERSION_1:
01266 <span class="preprocessor">#endif</span>
01267 <span class="preprocessor">#ifndef DISABLE_SNMPV2C</span>
01268 <span class="keywordflow">case</span> SNMP_VERSION_2c:
01269 <span class="preprocessor">#endif</span>
01270 <span class="keywordflow">case</span> SNMP_VERSION_3:
01271 <a class="code" href="group__callback.html#ga10">snmp_call_callbacks</a>(SNMP_CALLBACK_APPLICATION,
01272 SNMPD_CALLBACK_ACM_CHECK_INITIAL, &view_parms);
01273 <span class="keywordflow">return</span> view_parms.errorcode;
01274 }
01275 <span class="keywordflow">return</span> 1;
01276 }
01277
01285 <span class="keywordtype">int</span>
<a name="l01286" id="l01286"></a><a class="code" href="group__agent__registry.html#ga40">01286</a> <a class="code" href=
"group__agent__registry.html#ga40">netsnmp_acm_check_subtree</a>(<a class="code" href=
"structsnmp__pdu.html">netsnmp_pdu</a> *pdu, oid *name, size_t namelen)
01287 { <span class="comment">/* IN - pdu being checked */</span>
01288 <span class="keyword">struct </span>view_parameters view_parms;
01289 view_parms.pdu = pdu;
01290 view_parms.name = name;
01291 view_parms.namelen = namelen;
01292 view_parms.errorcode = 0;
01293 view_parms.check_subtree = 1;
01294
01295 <span class="keywordflow">if</span> (pdu-><a class="code" href=
"structsnmp__pdu.html#o9">flags</a> & UCD_MSG_FLAG_ALWAYS_IN_VIEW) {
01296 <span class="comment">/* Enable bypassing of view-based access control */</span>
01297 <span class="keywordflow">return</span> 0;
01298 }
01299
01300 <span class="keywordflow">switch</span> (pdu-><a class="code" href="structsnmp__pdu.html#o0">version</a>) {
01301 <span class="preprocessor">#ifndef DISABLE_SNMPV1</span>
01302 <span class="keywordflow">case</span> SNMP_VERSION_1:
01303 <span class="preprocessor">#endif</span>
01304 <span class="preprocessor">#ifndef DISABLE_SNMPV2C</span>
01305 <span class="keywordflow">case</span> SNMP_VERSION_2c:
01306 <span class="preprocessor">#endif</span>
01307 <span class="keywordflow">case</span> SNMP_VERSION_3:
01308 <a class="code" href="group__callback.html#ga10">snmp_call_callbacks</a>(SNMP_CALLBACK_APPLICATION,
01309 SNMPD_CALLBACK_ACM_CHECK_SUBTREE, &view_parms);
01310 <span class="keywordflow">return</span> view_parms.errorcode;
01311 }
01312 <span class="keywordflow">return</span> 1;
01313 }
01314
01315 <span class="preprocessor">#define SUBTREE_DEFAULT_CACHE_SIZE 8</span>
01316 <span class="preprocessor">#define SUBTREE_MAX_CACHE_SIZE 32</span>
01317 <span class="keywordtype">int</span> lookup_cache_size = 0; <span class=
"comment">/*enabled later after registrations are loaded */</span>
01318
01319 <span class="keyword">typedef</span> <span class="keyword">struct </span>lookup_cache_s {
01320 netsnmp_subtree *next;
01321 netsnmp_subtree *previous;
01322 } lookup_cache;
01323
01324 <span class="keyword">typedef</span> <span class="keyword">struct </span>lookup_cache_context_s {
01325 <span class="keywordtype">char</span> *context;
01326 <span class="keyword">struct </span>lookup_cache_context_s *next;
01327 <span class="keywordtype">int</span> thecachecount;
01328 <span class="keywordtype">int</span> currentpos;
01329 lookup_cache cache[SUBTREE_MAX_CACHE_SIZE];
01330 } lookup_cache_context;
01331
01332 <span class="keyword">static</span> lookup_cache_context *thecontextcache = NULL;
01333
01345 <span class="keywordtype">void</span>
<a name="l01346" id="l01346"></a><a class="code" href="group__agent__registry.html#ga9">01346</a> <a class="code" href=
"group__agent__registry.html#ga9">netsnmp_set_lookup_cache_size</a>(<span class="keywordtype">int</span> newsize) {
01347 <span class="keywordflow">if</span> (newsize < 0)
01348 lookup_cache_size = SUBTREE_DEFAULT_CACHE_SIZE;
01349 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (newsize < SUBTREE_MAX_CACHE_SIZE)
01350 lookup_cache_size = newsize;
01351 <span class="keywordflow">else</span>
01352 lookup_cache_size = SUBTREE_MAX_CACHE_SIZE;
01353 }
01354
01358 <span class="keywordtype">int</span>
<a name="l01359" id="l01359"></a><a class="code" href="group__agent__registry.html#ga10">01359</a> <a class="code" href=
"group__agent__registry.html#ga10">netsnmp_get_lookup_cache_size</a>(<span class="keywordtype">void</span>) {
01360 <span class="keywordflow">return</span> lookup_cache_size;
01361 }
01362
01363 NETSNMP_STATIC_INLINE lookup_cache_context *
01364 get_context_lookup_cache(<span class="keyword">const</span> <span class="keywordtype">char</span> *context) {
01365 lookup_cache_context *ptr;
01366 <span class="keywordflow">if</span> (!context)
01367 context = <span class="stringliteral">""</span>;
01368
01369 <span class="keywordflow">for</span>(ptr = thecontextcache; ptr; ptr = ptr->next) {
01370 <span class="keywordflow">if</span> (strcmp(ptr->context, context) == 0)
01371 <span class="keywordflow">break</span>;
01372 }
01373 <span class="keywordflow">if</span> (!ptr) {
01374 <span class="keywordflow">if</span> (netsnmp_subtree_find_first(context)) {
01375 ptr = <a class="code" href="group__util.html#ga39">SNMP_MALLOC_TYPEDEF</a>(lookup_cache_context);
01376 ptr->next = thecontextcache;
01377 ptr->context = strdup(context);
01378 thecontextcache = ptr;
01379 } <span class="keywordflow">else</span> {
01380 <span class="keywordflow">return</span> NULL;
01381 }
01382 }
01383 <span class="keywordflow">return</span> ptr;
01384 }
01385
01386 NETSNMP_STATIC_INLINE <span class="keywordtype">void</span>
01387 lookup_cache_add(<span class="keyword">const</span> <span class="keywordtype">char</span> *context,
01388 netsnmp_subtree *next, netsnmp_subtree *previous) {
01389 lookup_cache_context *cptr;
01390
01391 <span class="keywordflow">if</span> ((cptr = get_context_lookup_cache(context)) == NULL)
01392 <span class="keywordflow">return</span>;
01393
01394 <span class="keywordflow">if</span> (cptr->thecachecount < lookup_cache_size)
01395 cptr->thecachecount++;
01396
01397 cptr->cache[cptr->currentpos].next = next;
01398 cptr->cache[cptr->currentpos].previous = previous;
01399
01400 <span class="keywordflow">if</span> (++cptr->currentpos >= lookup_cache_size)
01401 cptr->currentpos = 0;
01402 }
01403
01404 NETSNMP_STATIC_INLINE <span class="keywordtype">void</span>
01405 lookup_cache_replace(lookup_cache *ptr,
01406 netsnmp_subtree *next, netsnmp_subtree *previous) {
01407
01408 ptr->next = next;
01409 ptr->previous = previous;
01410 }
01411
01412 NETSNMP_STATIC_INLINE lookup_cache *
01413 lookup_cache_find(<span class="keyword">const</span> <span class=
"keywordtype">char</span> *context, oid *name, size_t name_len,
01414 <span class="keywordtype">int</span> *retcmp) {
01415 lookup_cache_context *cptr;
01416 lookup_cache *ret = NULL;
01417 <span class="keywordtype">int</span> cmp;
01418 <span class="keywordtype">int</span> i;
01419
01420 <span class="keywordflow">if</span> ((cptr = get_context_lookup_cache(context)) == NULL)
01421 <span class="keywordflow">return</span> NULL;
01422
01423 <span class="keywordflow">for</span>(i = 0; i < cptr->thecachecount && i < lookup_cache_size; i++) {
01424 <span class="keywordflow">if</span> (cptr->cache[i].previous->start_a)
01425 cmp = <a class="code" href="group__library.html#ga103">snmp_oid_compare</a>(name, name_len,
01426 cptr->cache[i].previous->start_a,
01427 cptr->cache[i].previous->start_len);
01428 <span class="keywordflow">else</span>
01429 cmp = 1;
01430 <span class="keywordflow">if</span> (cmp >= 0) {
01431 *retcmp = cmp;
01432 ret = &(cptr->cache[i]);
01433 }
01434 }
01435 <span class="keywordflow">return</span> ret;
01436 }
01437
01438 NETSNMP_STATIC_INLINE <span class="keywordtype">void</span>
01439 invalidate_lookup_cache(<span class="keyword">const</span> <span class="keywordtype">char</span> *context) {
01440 lookup_cache_context *cptr;
01441 <span class="keywordflow">if</span> ((cptr = get_context_lookup_cache(context)) != NULL) {
01442 cptr->thecachecount = 0;
01443 cptr->currentpos = 0;
01444 }
01445 }
01446
01447 netsnmp_subtree *
01448 netsnmp_subtree_find_prev(oid *name, size_t len, netsnmp_subtree *subtree,
01449 <span class="keyword">const</span> <span class="keywordtype">char</span> *context_name)
01450 {
01451 lookup_cache *lookup_cache = NULL;
01452 netsnmp_subtree *myptr = NULL, *previous = NULL;
01453 <span class="keywordtype">int</span> cmp = 1;
01454 <span class="keywordtype">int</span> ll_off = 0;
01455
01456 <span class="keywordflow">if</span> (subtree) {
01457 myptr = subtree;
01458 } <span class="keywordflow">else</span> {
01459 <span class="comment">/* look through everything */</span>
01460 <span class="keywordflow">if</span> (lookup_cache_size) {
01461 lookup_cache = lookup_cache_find(context_name, name, len, &cmp);
01462 <span class="keywordflow">if</span> (lookup_cache) {
01463 myptr = lookup_cache->next;
01464 previous = lookup_cache->previous;
01465 }
01466 <span class="keywordflow">if</span> (!myptr)
01467 myptr = netsnmp_subtree_find_first(context_name);
01468 } <span class="keywordflow">else</span> {
01469 myptr = netsnmp_subtree_find_first(context_name);
01470 }
01471 }
01472
01473 <span class="comment">/*</span>
01474 <span class="comment"> * this optimization causes a segfault on sf cf alpha-linux1.</span>
01475 <span class="comment"> * ifdef out until someone figures out why and fixes it. xxx-rks 20051117</span>
01476 <span class="comment"> */</span>
01477 <span class="preprocessor">#ifndef __alpha</span>
01478 <span class="preprocessor">#define WTEST_OPTIMIZATION 1</span>
01479 <span class="preprocessor">#endif</span>
01480 <span class="preprocessor">#ifdef WTEST_OPTIMIZATION</span>
01481 DEBUGMSGTL((<span class="stringliteral">"wtest"</span>,<span class="stringliteral">"oid in: "</span>));
01482 DEBUGMSGOID((<span class="stringliteral">"wtest"</span>, name, len));
01483 DEBUGMSG((<span class="stringliteral">"wtest"</span>,<span class="stringliteral">"\n"</span>));
01484 <span class="preprocessor">#endif</span>
01485 <span class="keywordflow">for</span> (; myptr != NULL; previous = myptr, myptr = myptr->next) {
01486 <span class="preprocessor">#ifdef WTEST_OPTIMIZATION</span>
01487 <span class="comment">/* Compare the incoming oid with the linked list. If we have</span>
01488 <span class="comment"> results of previous compares, its faster to make sure the</span>
01489 <span class="comment"> length we differed in the last check is greater than the</span>
01490 <span class="comment"> length between this pointer and the last then we don't need</span>
01491 <span class="comment"> to actually perform a comparison */</span>
01492 DEBUGMSGTL((<span class="stringliteral">"wtest"</span>,<span class="stringliteral">"oid cmp: "</span>));
01493 DEBUGMSGOID((<span class="stringliteral">"wtest"</span>, myptr->start_a, myptr->start_len));
01494 DEBUGMSG((<span class="stringliteral">"wtest"</span>,<span class=
"stringliteral">" --- off = %d, in off = %d test = %d\n"</span>,
01495 myptr->oid_off, ll_off,
01496 !(ll_off && myptr->oid_off &&
01497 myptr->oid_off > ll_off)));
01498 <span class=
"keywordflow">if</span> (!(ll_off && myptr->oid_off && myptr->oid_off > ll_off) &&
01499 <a class="code" href="group__library.html#ga104">netsnmp_oid_compare_ll</a>(name, len,
01500 myptr->start_a, myptr->start_len,
01501 &ll_off) < 0) {
01502 <span class="preprocessor">#else</span>
01503 <span class="keywordflow">if</span> (<a class="code" href=
"group__library.html#ga103">snmp_oid_compare</a>(name, len, myptr->start_a, myptr->start_len) < 0) {
01504 <span class="preprocessor">#endif</span>
01505 <span class="keywordflow">if</span> (lookup_cache_size && previous && cmp) {
01506 <span class="keywordflow">if</span> (lookup_cache) {
01507 lookup_cache_replace(lookup_cache, myptr, previous);
01508 } <span class="keywordflow">else</span> {
01509 lookup_cache_add(context_name, myptr, previous);
01510 }
01511 }
01512 <span class="keywordflow">return</span> previous;
01513 }
01514 }
01515 <span class="keywordflow">return</span> previous;
01516 }
01517
01518 netsnmp_subtree *
01519 netsnmp_subtree_find_next(oid *name, size_t len,
01520 netsnmp_subtree *subtree, <span class="keyword">const</span> <span class=
"keywordtype">char</span> *context_name)
01521 {
01522 netsnmp_subtree *myptr = NULL;
01523
01524 myptr = netsnmp_subtree_find_prev(name, len, subtree, context_name);
01525
01526 <span class="keywordflow">if</span> (myptr != NULL) {
01527 myptr = myptr->next;
01528 <span class="keywordflow">while</span> (myptr != NULL && (myptr->variables == NULL ||
01529 myptr->variables_len == 0)) {
01530 myptr = myptr->next;
01531 }
01532 <span class="keywordflow">return</span> myptr;
01533 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (subtree != NULL && <a class="code"
href="group__library.html#ga103">snmp_oid_compare</a>(name, len,
01534 subtree->start_a, subtree->start_len) < 0) {
01535 <span class="keywordflow">return</span> subtree;
01536 } <span class="keywordflow">else</span> {
01537 <span class="keywordflow">return</span> NULL;
01538 }
01539 }
01540
01541 netsnmp_subtree *
01542 netsnmp_subtree_find(oid *name, size_t len, netsnmp_subtree *subtree,
01543 <span class="keyword">const</span> <span class="keywordtype">char</span> *context_name)
01544 {
01545 netsnmp_subtree *myptr;
01546
01547 myptr = netsnmp_subtree_find_prev(name, len, subtree, context_name);
01548 <span class="keywordflow">if</span> (myptr && myptr->end_a &&
01549 <a class="code" href=
"group__library.html#ga103">snmp_oid_compare</a>(name, len, myptr->end_a, myptr->end_len)<0) {
01550 <span class="keywordflow">return</span> myptr;
01551 }
01552
01553 <span class="keywordflow">return</span> NULL;
01554 }
01555
01556 <a class="code" href="structsnmp__session.html">netsnmp_session</a> *
01557 get_session_for_oid(oid *name, size_t len, <span class="keyword">const</span> <span class=
"keywordtype">char</span> *context_name)
01558 {
01559 netsnmp_subtree *myptr;
01560
01561 myptr = netsnmp_subtree_find_prev(name, len,
01562 netsnmp_subtree_find_first(context_name),
01563 context_name);
01564
01565 <span class="keywordflow">while</span> (myptr && myptr->variables == NULL) {
01566 myptr = myptr-><a class="code" href="structsnmp__session.html#o5">next</a>;
01567 }
01568
01569 <span class="keywordflow">if</span> (myptr == NULL) {
01570 <span class="keywordflow">return</span> NULL;
01571 } <span class="keywordflow">else</span> {
01572 <span class="keywordflow">return</span> myptr->session;
01573 }
01574 }
01575
01576 <span class="keywordtype">void</span>
01577 setup_tree(<span class="keywordtype">void</span>)
01578 {
01579 oid ccitt[1] = { 0 };
01580 oid iso[1] = { 1 };
01581 oid joint_ccitt_iso[1] = { 2 };
01582
01583 <span class="preprocessor">#ifdef USING_AGENTX_SUBAGENT_MODULE</span>
01584 <span class="keywordtype">int</span> role = netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
01585 NETSNMP_DS_AGENT_ROLE);
01586
01587 <a class="code" href=
"group__default__store.html#ga8">netsnmp_ds_set_boolean</a>(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE,
01588 MASTER_AGENT);
01589 <span class="preprocessor">#endif</span>
01590
01591 <span class="comment">/* </span>
01592 <span class="comment"> * we need to have the oid's in the heap, that we can *free* it for every case, </span>
01593 <span class="comment"> * thats the purpose of the duplicate_objid's</span>
01594 <span class="comment"> */</span>
01595 netsnmp_register_null(snmp_duplicate_objid(ccitt, 1), 1);
01596 netsnmp_register_null(snmp_duplicate_objid(iso, 1), 1);
01597 netsnmp_register_null(snmp_duplicate_objid(joint_ccitt_iso, 1), 1);
01598
01599 <span class="preprocessor">#ifdef USING_AGENTX_SUBAGENT_MODULE</span>
01600 <a class="code" href=
"group__default__store.html#ga8">netsnmp_ds_set_boolean</a>(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE,
01601 role);
01602 <span class="preprocessor">#endif</span>
01603 }
01604
01605 <span class="keywordtype">int</span>
01606 remove_tree_entry (oid *name, size_t len) {
01607
01608 netsnmp_subtree *sub = NULL;
01609
01610 <span class="keywordflow">if</span> ((sub = netsnmp_subtree_find(name, len, NULL, <span class=
"stringliteral">""</span>)) == NULL) {
01611 <span class="keywordflow">return</span> MIB_NO_SUCH_REGISTRATION;
01612 }
01613
01614 <span class="keywordflow">return</span> <a class="code" href=
"group__agent__registry.html#ga32">unregister_mib_context</a>(name, len, sub->priority,
01615 sub->range_subid, sub->range_ubound, <span class="stringliteral">""</span>);
01616
01617 }
01618
01619
01620 <span class="keywordtype">void</span>
01621 shutdown_tree(<span class="keywordtype">void</span>) {
01622 oid ccitt[1] = { 0 };
01623 oid iso[1] = { 1 };
01624 oid joint_ccitt_iso[1] = { 2 };
01625
01626 DEBUGMSGTL((<span class="stringliteral">"agent_registry"</span>, <span class=
"stringliteral">"shut down tree\n"</span>));
01627
01628 remove_tree_entry(joint_ccitt_iso, 1);
01629 remove_tree_entry(iso, 1);
01630 remove_tree_entry(ccitt, 1);
01631
01632 }
01633
01634 <span class="keywordtype">void</span>
01635 clear_subtree (netsnmp_subtree *sub) {
01636
01637 netsnmp_subtree *nxt;
01638
01639 <span class="keywordflow">if</span> (sub == NULL)
01640 <span class="keywordflow">return</span>;
01641
01642 <span class="keywordflow">for</span>(nxt = sub; nxt;) {
01643 <span class="keywordflow">if</span> (nxt->children != NULL) {
01644 clear_subtree(nxt->children);
01645 }
01646 sub = nxt;
01647 nxt = nxt-><a class="code" href="structsnmp__session.html#o5">next</a>;
01648 netsnmp_subtree_free(sub);
01649 }
01650
01651 }
01652
01653 <span class="keywordtype">void</span>
01654 clear_lookup_cache(<span class="keywordtype">void</span>) {
01655
01656 lookup_cache_context *ptr = NULL, *next = NULL;
01657
01658 ptr = thecontextcache;
01659 <span class="keywordflow">while</span> (ptr) {
01660 next = ptr-><a class="code" href="structsnmp__session.html#o5">next</a>;
01661 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(ptr->context);
01662 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(ptr);
01663 ptr = next;
01664 }
01665 thecontextcache = NULL; <span class="comment">/* !!! */</span>
01666 }
01667
01668 <span class="keywordtype">void</span>
01669 clear_context(<span class="keywordtype">void</span>) {
01670
01671 subtree_context_cache *ptr = NULL, *next = NULL;
01672
01673 DEBUGMSGTL((<span class="stringliteral">"agent_registry"</span>, <span class=
"stringliteral">"clear context\n"</span>));
01674
01675 ptr = get_top_context_cache();
01676 <span class="keywordflow">while</span> (ptr) {
01677 next = ptr-><a class="code" href="structsnmp__session.html#o5">next</a>;
01678
01679 <span class="keywordflow">if</span> (ptr->first_subtree) {
01680 clear_subtree(ptr->first_subtree);
01681 }
01682
01683 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(ptr->context_name);
01684 <a class="code" href="group__util.html#ga36">SNMP_FREE</a>(ptr);
01685
01686 ptr = next;
01687 }
01688 context_subtrees = NULL; <span class="comment">/* !!! */</span>
01689 clear_lookup_cache();
01690 }
01691
01692 <span class="keyword">extern</span> <span class="keywordtype">void</span> dump_idx_registry(<span class=
"keywordtype">void</span>);
01693 <span class="keywordtype">void</span>
01694 dump_registry(<span class="keywordtype">void</span>)
01695 {
01696 <span class="keyword">struct </span>variable *vp = NULL;
01697 netsnmp_subtree *myptr, *myptr2;
01698 u_char *s = NULL, *e = NULL, *v = NULL;
01699 size_t sl = 256, el = 256, vl = 256, sl_o = 0, el_o = 0, vl_o = 0;
01700 <span class="keywordtype">int</span> i = 0;
01701
01702 <span class="keywordflow">if</span> ((s = (u_char *) calloc(sl, 1)) != NULL &&
01703 (e = (u_char *) calloc(sl, 1)) != NULL &&
01704 (v = (u_char *) calloc(sl, 1)) != NULL) {
01705
01706 subtree_context_cache *ptr;
01707 <span class="keywordflow">for</span> (ptr = context_subtrees; ptr; ptr = ptr->next) {
01708 printf(<span class="stringliteral">"Subtrees for Context: %s\n"</span>, ptr->context_name);
01709 <span class="keywordflow">for</span> (myptr = ptr->first_subtree; myptr != NULL;
01710 myptr = myptr->next) {
01711 sl_o = el_o = vl_o = 0;
01712
01713 <span class="keywordflow">if</span> (!sprint_realloc_objid(&s, &sl, &sl_o, 1,
01714 myptr->start_a,
01715 myptr->start_len)) {
01716 <span class="keywordflow">break</span>;
01717 }
01718 <span class="keywordflow">if</span