Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / net-snmp / snmplib / oid_stash.c
1 #ifdef BRCM_SNMP_SUPPORT
2 #include <net-snmp/net-snmp-config.h>
3
4 #include <string.h>
5
6 #include <stdlib.h>
7 #include <sys/types.h>
8
9 #if HAVE_DMALLOC_H
10 #include <dmalloc.h>
11 #endif
12
13 #include <net-snmp/net-snmp-includes.h>
14
15 /*
16  * xxx-rks: when you have some spare time:
17  *
18  * a) add get-next access
19  * 
20  * b) basically, everything currently creates one node per sub-oid,
21  *    which is less than optimal. add code to create nodes with the
22  *    longest possible OID per node, and split nodes when necessary
23  *    during adds.
24  *
25  * c) If you are feeling really ambitious, also merge split nodes if
26  *    possible on a delete.
27  *
28  */
29
30 /***************************************************************************
31  *
32  *
33  ***************************************************************************/
34
35 /*
36  * Create an netsnmp_oid_stash node
37  *
38  * @param mysize  the size of the child pointer array
39  *
40  * @return NULL on error, otherwise the newly allocated node
41  */
42 netsnmp_oid_stash_node *
43 netsnmp_oid_stash_create_sized_node(size_t mysize)
44 {
45     netsnmp_oid_stash_node *ret;
46     ret = SNMP_MALLOC_TYPEDEF(netsnmp_oid_stash_node);
47     if (!ret)
48         return NULL;
49     ret->children = calloc(mysize, sizeof(netsnmp_oid_stash_node *));
50     if (!ret->children) {
51         free(ret);
52         return NULL;
53     }
54     ret->children_size = mysize;
55     return ret;
56 }
57
58 NETSNMP_INLINE netsnmp_oid_stash_node *
59 netsnmp_oid_stash_create_node(void)
60 {
61     return netsnmp_oid_stash_create_sized_node(OID_STASH_CHILDREN_SIZE);
62 }
63
64 /** adds data to the stash at a given oid.
65  * returns SNMPERR_SUCCESS on success.
66  * returns SNMPERR_GENERR if data is already there.
67  * returns SNMPERR_MALLOC on malloc failures or if arguments passed in
68  *   with NULL values.
69  */
70 int
71 netsnmp_oid_stash_add_data(netsnmp_oid_stash_node **root,
72                            oid * lookup, size_t lookup_len, void *mydata)
73 {
74     netsnmp_oid_stash_node *curnode, *tmpp, *loopp;
75     unsigned int    i;
76
77     if (!root || !lookup || lookup_len == 0)
78         return SNMPERR_GENERR;
79
80     if (!*root) {
81         *root = netsnmp_oid_stash_create_node();
82         if (!*root)
83             return SNMPERR_MALLOC;
84     }
85     tmpp = NULL;
86     for (curnode = *root, i = 0; i < lookup_len; i++) {
87         tmpp = curnode->children[lookup[i] % curnode->children_size];
88         if (!tmpp) {
89             /*
90              * no child in array at all 
91              */
92             tmpp = curnode->children[lookup[i] % curnode->children_size] =
93                 netsnmp_oid_stash_create_node();
94             tmpp->value = lookup[i];
95         } else {
96             for (loopp = tmpp; loopp; loopp = loopp->next_sibling) {
97                 if (loopp->value == lookup[i])
98                     break;
99             }
100             if (loopp) {
101                 tmpp = loopp;
102             } else {
103                 /*
104                  * none exists.  Create it 
105                  */
106                 loopp = netsnmp_oid_stash_create_node();
107                 loopp->value = lookup[i];
108                 loopp->next_sibling = tmpp;
109                 tmpp->prev_sibling = loopp;
110                 curnode->children[lookup[i] % curnode->children_size] =
111                     loopp;
112                 tmpp = loopp;
113             }
114             /*
115              * tmpp now points to the proper node 
116              */
117         }
118         curnode = tmpp;
119     }
120     /*
121      * tmpp now points to the exact match 
122      */
123     if (curnode->thedata)
124         return SNMPERR_GENERR;
125     if (NULL == tmpp)
126         return SNMPERR_GENERR;
127     tmpp->thedata = mydata;
128     return SNMPERR_SUCCESS;
129 }
130
131 /** returns a node associated with a given OID.
132  */
133 netsnmp_oid_stash_node *
134 netsnmp_oid_stash_get_node(netsnmp_oid_stash_node *root,
135                            oid * lookup, size_t lookup_len)
136 {
137     netsnmp_oid_stash_node *curnode, *tmpp, *loopp;
138     unsigned int    i;
139
140     if (!root)
141         return NULL;
142     tmpp = NULL;
143     for (curnode = root, i = 0; i < lookup_len; i++) {
144         tmpp = curnode->children[lookup[i] % curnode->children_size];
145         if (!tmpp) {
146             return NULL;
147         } else {
148             for (loopp = tmpp; loopp; loopp = loopp->next_sibling) {
149                 if (loopp->value == lookup[i])
150                     break;
151             }
152             if (loopp) {
153                 tmpp = loopp;
154             } else {
155                 return NULL;
156             }
157         }
158         curnode = tmpp;
159     }
160     return tmpp;
161 }
162
163 /** returns a data pointer associated with a given OID.
164  */
165 void           *
166 netsnmp_oid_stash_get_data(netsnmp_oid_stash_node *root,
167                            oid * lookup, size_t lookup_len)
168 {
169     netsnmp_oid_stash_node *ret;
170     ret = netsnmp_oid_stash_get_node(root, lookup, lookup_len);
171     if (ret)
172         return ret->thedata;
173     return NULL;
174 }
175
176 int
177 netsnmp_oid_stash_store_all(int majorID, int minorID,
178                             void *serverarg, void *clientarg) {
179     oid oidbase[MAX_OID_LEN];
180     netsnmp_oid_stash_save_info *sinfo;
181     
182     if (!clientarg)
183         return SNMP_ERR_NOERROR;
184     
185     sinfo = clientarg;
186     netsnmp_oid_stash_store(*(sinfo->root), sinfo->token, sinfo->dumpfn,
187                             oidbase,0);
188     return SNMP_ERR_NOERROR;
189 }
190
191 void
192 netsnmp_oid_stash_store(netsnmp_oid_stash_node *root,
193                         const char *tokenname, NetSNMPStashDump *dumpfn,
194                         oid *curoid, size_t curoid_len) {
195
196     char buf[SNMP_MAXBUF];
197     netsnmp_oid_stash_node *tmpp;
198     char *cp;
199     char *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
200                                           NETSNMP_DS_LIB_APPTYPE);
201     int i;
202     
203     if (!tokenname || !root || !curoid || !dumpfn)
204         return;
205
206     for (i = 0; i < root->children_size; i++) {
207         if (root->children[i]) {
208             for (tmpp = root->children[i]; tmpp; tmpp = tmpp->next_sibling) {
209                 curoid[curoid_len] = tmpp->value;
210                 if (tmpp->thedata) {
211                     snprintf(buf, sizeof(buf), "%s ", tokenname);
212                     cp = read_config_save_objid(buf+strlen(buf), curoid,
213                                                 curoid_len+1);
214                     *cp++ = ' ';
215                     *cp = '\0';
216                     if ((*dumpfn)(cp, sizeof(buf) - strlen(buf),
217                                   tmpp->thedata, tmpp))
218                         read_config_store(appname, buf);
219                 }
220                 netsnmp_oid_stash_store(tmpp, tokenname, dumpfn,
221                                         curoid, curoid_len+1);
222             }
223         }
224     }
225 }
226
227 void
228 oid_stash_dump(netsnmp_oid_stash_node *root, char *prefix)
229 {
230     char            myprefix[MAX_OID_LEN * 4];
231     netsnmp_oid_stash_node *tmpp;
232     int             prefix_len = strlen(prefix) + 1;    /* actually it's +2 */
233     unsigned int    i;
234
235     memset(myprefix, ' ', MAX_OID_LEN * 4);
236     myprefix[prefix_len] = '\0';
237
238     for (i = 0; i < root->children_size; i++) {
239         if (root->children[i]) {
240             for (tmpp = root->children[i]; tmpp; tmpp = tmpp->next_sibling) {
241                 printf("%s%ld@%d:\n", prefix, tmpp->value, i);
242                 oid_stash_dump(tmpp, myprefix);
243             }
244         }
245     }
246 }
247 #endif /* BRCM_SNMP_SUPPORT */