| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    |||
2  | 
    |||
3  | 
    /*  | 
    ||
4  | 
    * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>  | 
    ||
5  | 
    *  | 
    ||
6  | 
    * Permission to use, copy, modify, and distribute this software for any  | 
    ||
7  | 
    * purpose with or without fee is hereby granted, provided that the above  | 
    ||
8  | 
    * copyright notice and this permission notice appear in all copies.  | 
    ||
9  | 
    *  | 
    ||
10  | 
    * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  | 
    ||
11  | 
    * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF  | 
    ||
12  | 
    * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR  | 
    ||
13  | 
    * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES  | 
    ||
14  | 
    * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN  | 
    ||
15  | 
    * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  | 
    ||
16  | 
    * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  | 
    ||
17  | 
    */  | 
    ||
18  | 
    |||
19  | 
    #include <sys/queue.h>  | 
    ||
20  | 
    #include <sys/types.h>  | 
    ||
21  | 
    #include <sys/stat.h>  | 
    ||
22  | 
    #include <sys/socket.h>  | 
    ||
23  | 
    #include <sys/un.h>  | 
    ||
24  | 
    #include <sys/tree.h>  | 
    ||
25  | 
    #include <sys/sysctl.h>  | 
    ||
26  | 
    |||
27  | 
    #include <net/if.h>  | 
    ||
28  | 
    #include <net/if_dl.h>  | 
    ||
29  | 
    #include <net/if_arp.h>  | 
    ||
30  | 
    #include <net/if_media.h>  | 
    ||
31  | 
    #include <net/route.h>  | 
    ||
32  | 
    #include <netinet/in.h>  | 
    ||
33  | 
    #include <netinet/if_ether.h>  | 
    ||
34  | 
    #include <arpa/inet.h>  | 
    ||
35  | 
    |||
36  | 
    #include <stdlib.h>  | 
    ||
37  | 
    #include <stdio.h>  | 
    ||
38  | 
    #include <errno.h>  | 
    ||
39  | 
    #include <event.h>  | 
    ||
40  | 
    #include <fcntl.h>  | 
    ||
41  | 
    #include <string.h>  | 
    ||
42  | 
    #include <unistd.h>  | 
    ||
43  | 
    #include <limits.h>  | 
    ||
44  | 
    #include <pwd.h>  | 
    ||
45  | 
    #include <vis.h>  | 
    ||
46  | 
    |||
47  | 
    #include "snmpd.h"  | 
    ||
48  | 
    #include "mib.h"  | 
    ||
49  | 
    |||
50  | 
    #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))  | 
    ||
51  | 
    |||
52  | 
    RB_HEAD(oidtree, oid);  | 
    ||
53  | 
    RB_PROTOTYPE(oidtree, oid, o_element, smi_oid_cmp);  | 
    ||
54  | 
    struct oidtree smi_oidtree;  | 
    ||
55  | 
    |||
56  | 
    RB_HEAD(keytree, oid);  | 
    ||
57  | 
    RB_PROTOTYPE(keytree, oid, o_keyword, smi_key_cmp);  | 
    ||
58  | 
    struct keytree smi_keytree;  | 
    ||
59  | 
    |||
60  | 
    u_long  | 
    ||
61  | 
    smi_getticks(void)  | 
    ||
62  | 
    { | 
    ||
63  | 
    struct timeval now, run;  | 
    ||
64  | 
    u_long ticks;  | 
    ||
65  | 
    |||
66  | 
    gettimeofday(&now, NULL);  | 
    ||
67  | 
    if (timercmp(&now, &snmpd_env->sc_starttime, <=))  | 
    ||
68  | 
    return (0);  | 
    ||
69  | 
    timersub(&now, &snmpd_env->sc_starttime, &run);  | 
    ||
70  | 
    ticks = run.tv_sec * 100;  | 
    ||
71  | 
    if (run.tv_usec)  | 
    ||
72  | 
    ticks += run.tv_usec / 10000;  | 
    ||
73  | 
    |||
74  | 
    return (ticks);  | 
    ||
75  | 
    }  | 
    ||
76  | 
    |||
77  | 
    void  | 
    ||
78  | 
    smi_oidlen(struct ber_oid *o)  | 
    ||
79  | 
    { | 
    ||
80  | 
    size_t i;  | 
    ||
81  | 
    |||
82  | 
    ✓✗✓✓ | 
    77032  | 
    for (i = 0; i < BER_MAX_OID_LEN && o->bo_id[i] != 0; i++)  | 
    
83  | 
    ;  | 
    ||
84  | 
    2356  | 
    o->bo_n = i;  | 
    |
85  | 
    2356  | 
    }  | 
    |
86  | 
    |||
87  | 
    void  | 
    ||
88  | 
    smi_scalar_oidlen(struct ber_oid *o)  | 
    ||
89  | 
    { | 
    ||
90  | 
    smi_oidlen(o);  | 
    ||
91  | 
    |||
92  | 
    /* Append .0. */  | 
    ||
93  | 
    if (o->bo_n < BER_MAX_OID_LEN)  | 
    ||
94  | 
    o->bo_n++;  | 
    ||
95  | 
    }  | 
    ||
96  | 
    |||
97  | 
    char *  | 
    ||
98  | 
    smi_oid2string(struct ber_oid *o, char *buf, size_t len, size_t skip)  | 
    ||
99  | 
    { | 
    ||
100  | 
    char str[256];  | 
    ||
101  | 
    struct oid *value, key;  | 
    ||
102  | 
    size_t i, lookup = 1;  | 
    ||
103  | 
    |||
104  | 
    bzero(buf, len);  | 
    ||
105  | 
    bzero(&key, sizeof(key));  | 
    ||
106  | 
    bcopy(o, &key.o_id, sizeof(struct ber_oid));  | 
    ||
107  | 
    key.o_flags |= OID_KEY; /* do not match wildcards */  | 
    ||
108  | 
    |||
109  | 
    if (snmpd_env->sc_flags & SNMPD_F_NONAMES)  | 
    ||
110  | 
    lookup = 0;  | 
    ||
111  | 
    |||
112  | 
    	for (i = 0; i < o->bo_n; i++) { | 
    ||
113  | 
    key.o_oidlen = i + 1;  | 
    ||
114  | 
    if (lookup && skip > i)  | 
    ||
115  | 
    continue;  | 
    ||
116  | 
    if (lookup &&  | 
    ||
117  | 
    (value = RB_FIND(oidtree, &smi_oidtree, &key)) != NULL)  | 
    ||
118  | 
    snprintf(str, sizeof(str), "%s", value->o_name);  | 
    ||
119  | 
    else  | 
    ||
120  | 
    snprintf(str, sizeof(str), "%d", key.o_oid[i]);  | 
    ||
121  | 
    strlcat(buf, str, len);  | 
    ||
122  | 
    if (i < (o->bo_n - 1))  | 
    ||
123  | 
    strlcat(buf, ".", len);  | 
    ||
124  | 
    }  | 
    ||
125  | 
    |||
126  | 
    return (buf);  | 
    ||
127  | 
    }  | 
    ||
128  | 
    |||
129  | 
    int  | 
    ||
130  | 
    smi_string2oid(const char *oidstr, struct ber_oid *o)  | 
    ||
131  | 
    { | 
    ||
132  | 
    char *sp, *p, str[BUFSIZ];  | 
    ||
133  | 
    const char *errstr;  | 
    ||
134  | 
    struct oid *oid;  | 
    ||
135  | 
    struct ber_oid ko;  | 
    ||
136  | 
    |||
137  | 
    if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))  | 
    ||
138  | 
    return (-1);  | 
    ||
139  | 
    bzero(o, sizeof(*o));  | 
    ||
140  | 
    |||
141  | 
    /*  | 
    ||
142  | 
    * Parse OID strings in the common form n.n.n or n-n-n.  | 
    ||
143  | 
    * Based on ber_string2oid with additional support for symbolic names.  | 
    ||
144  | 
    */  | 
    ||
145  | 
    	for (p = sp = str; p != NULL; sp = p) { | 
    ||
146  | 
    if ((p = strpbrk(p, ".-")) != NULL)  | 
    ||
147  | 
    *p++ = '\0';  | 
    ||
148  | 
    		if ((oid = smi_findkey(sp)) != NULL) { | 
    ||
149  | 
    bcopy(&oid->o_id, &ko, sizeof(ko));  | 
    ||
150  | 
    if (o->bo_n && ber_oid_cmp(o, &ko) != 2)  | 
    ||
151  | 
    return (-1);  | 
    ||
152  | 
    bcopy(&ko, o, sizeof(*o));  | 
    ||
153  | 
    errstr = NULL;  | 
    ||
154  | 
    		} else { | 
    ||
155  | 
    o->bo_id[o->bo_n++] =  | 
    ||
156  | 
    strtonum(sp, 0, UINT_MAX, &errstr);  | 
    ||
157  | 
    }  | 
    ||
158  | 
    if (errstr || o->bo_n > BER_MAX_OID_LEN)  | 
    ||
159  | 
    return (-1);  | 
    ||
160  | 
    }  | 
    ||
161  | 
    |||
162  | 
    return (0);  | 
    ||
163  | 
    }  | 
    ||
164  | 
    |||
165  | 
    void  | 
    ||
166  | 
    smi_delete(struct oid *oid)  | 
    ||
167  | 
    { | 
    ||
168  | 
    struct oid key, *value;  | 
    ||
169  | 
    |||
170  | 
    bzero(&key, sizeof(key));  | 
    ||
171  | 
    bcopy(&oid->o_id, &key.o_id, sizeof(struct ber_oid));  | 
    ||
172  | 
    if ((value = RB_FIND(oidtree, &smi_oidtree, &key)) != NULL &&  | 
    ||
173  | 
    value == oid)  | 
    ||
174  | 
    RB_REMOVE(oidtree, &smi_oidtree, value);  | 
    ||
175  | 
    |||
176  | 
    free(oid->o_data);  | 
    ||
177  | 
    	if (oid->o_flags & OID_DYNAMIC) { | 
    ||
178  | 
    free(oid->o_name);  | 
    ||
179  | 
    free(oid);  | 
    ||
180  | 
    }  | 
    ||
181  | 
    }  | 
    ||
182  | 
    |||
183  | 
    int  | 
    ||
184  | 
    smi_insert(struct oid *oid)  | 
    ||
185  | 
    { | 
    ||
186  | 
    struct oid key, *value;  | 
    ||
187  | 
    |||
188  | 
    if ((oid->o_flags & OID_TABLE) && oid->o_get == NULL)  | 
    ||
189  | 
    		fatalx("smi_insert: invalid MIB table"); | 
    ||
190  | 
    |||
191  | 
    bzero(&key, sizeof(key));  | 
    ||
192  | 
    bcopy(&oid->o_id, &key.o_id, sizeof(struct ber_oid));  | 
    ||
193  | 
    value = RB_FIND(oidtree, &smi_oidtree, &key);  | 
    ||
194  | 
    if (value != NULL)  | 
    ||
195  | 
    return (-1);  | 
    ||
196  | 
    |||
197  | 
    RB_INSERT(oidtree, &smi_oidtree, oid);  | 
    ||
198  | 
    return (0);  | 
    ||
199  | 
    }  | 
    ||
200  | 
    |||
201  | 
    void  | 
    ||
202  | 
    smi_mibtree(struct oid *oids)  | 
    ||
203  | 
    { | 
    ||
204  | 
    struct oid *oid, *decl;  | 
    ||
205  | 
    size_t i;  | 
    ||
206  | 
    |||
207  | 
    ✓✓ | 4724  | 
    	for (i = 0; oids[i].o_oid[0] != 0; i++) { | 
    
208  | 
    oid = &oids[i];  | 
    ||
209  | 
    2356  | 
    smi_oidlen(&oid->o_id);  | 
    |
210  | 
    ✓✗ | 2356  | 
    		if (oid->o_name != NULL) { | 
    
211  | 
    ✗✓✗✗ | 
    2356  | 
    if ((oid->o_flags & OID_TABLE) && oid->o_get == NULL)  | 
    
212  | 
    				fatalx("smi_mibtree: invalid MIB table"); | 
    ||
213  | 
    2356  | 
    RB_INSERT(oidtree, &smi_oidtree, oid);  | 
    |
214  | 
    2356  | 
    RB_INSERT(keytree, &smi_keytree, oid);  | 
    |
215  | 
    2356  | 
    continue;  | 
    |
216  | 
    }  | 
    ||
217  | 
    decl = RB_FIND(oidtree, &smi_oidtree, oid);  | 
    ||
218  | 
    if (decl == NULL)  | 
    ||
219  | 
    			fatalx("smi_mibtree: undeclared MIB"); | 
    ||
220  | 
    decl->o_flags = oid->o_flags;  | 
    ||
221  | 
    decl->o_get = oid->o_get;  | 
    ||
222  | 
    decl->o_set = oid->o_set;  | 
    ||
223  | 
    decl->o_table = oid->o_table;  | 
    ||
224  | 
    decl->o_val = oid->o_val;  | 
    ||
225  | 
    decl->o_data = oid->o_data;  | 
    ||
226  | 
    }  | 
    ||
227  | 
    4  | 
    }  | 
    |
228  | 
    |||
229  | 
    int  | 
    ||
230  | 
    smi_init(void)  | 
    ||
231  | 
    { | 
    ||
232  | 
    /* Initialize the Structure of Managed Information (SMI) */  | 
    ||
233  | 
    8  | 
    RB_INIT(&smi_oidtree);  | 
    |
234  | 
    4  | 
    mib_init();  | 
    |
235  | 
    4  | 
    return (0);  | 
    |
236  | 
    }  | 
    ||
237  | 
    |||
238  | 
    struct oid *  | 
    ||
239  | 
    smi_find(struct oid *oid)  | 
    ||
240  | 
    { | 
    ||
241  | 
    return (RB_FIND(oidtree, &smi_oidtree, oid));  | 
    ||
242  | 
    }  | 
    ||
243  | 
    |||
244  | 
    struct oid *  | 
    ||
245  | 
    smi_findkey(char *name)  | 
    ||
246  | 
    { | 
    ||
247  | 
    struct oid oid;  | 
    ||
248  | 
    if (name == NULL)  | 
    ||
249  | 
    return (NULL);  | 
    ||
250  | 
    oid.o_name = name;  | 
    ||
251  | 
    return (RB_FIND(keytree, &smi_keytree, &oid));  | 
    ||
252  | 
    }  | 
    ||
253  | 
    |||
254  | 
    struct oid *  | 
    ||
255  | 
    smi_next(struct oid *oid)  | 
    ||
256  | 
    { | 
    ||
257  | 
    return (RB_NEXT(oidtree, &smi_oidtree, oid));  | 
    ||
258  | 
    }  | 
    ||
259  | 
    |||
260  | 
    struct oid *  | 
    ||
261  | 
    smi_foreach(struct oid *oid, u_int flags)  | 
    ||
262  | 
    { | 
    ||
263  | 
    /*  | 
    ||
264  | 
    * Traverse the tree of MIBs with the option to check  | 
    ||
265  | 
    * for specific OID flags.  | 
    ||
266  | 
    */  | 
    ||
267  | 
    	if (oid == NULL) { | 
    ||
268  | 
    oid = RB_MIN(oidtree, &smi_oidtree);  | 
    ||
269  | 
    if (oid == NULL)  | 
    ||
270  | 
    return (NULL);  | 
    ||
271  | 
    if (flags == 0 || (oid->o_flags & flags))  | 
    ||
272  | 
    return (oid);  | 
    ||
273  | 
    }  | 
    ||
274  | 
    	for (;;) { | 
    ||
275  | 
    oid = RB_NEXT(oidtree, &smi_oidtree, oid);  | 
    ||
276  | 
    if (oid == NULL)  | 
    ||
277  | 
    break;  | 
    ||
278  | 
    if (flags == 0 || (oid->o_flags & flags))  | 
    ||
279  | 
    return (oid);  | 
    ||
280  | 
    }  | 
    ||
281  | 
    |||
282  | 
    return (oid);  | 
    ||
283  | 
    }  | 
    ||
284  | 
    |||
285  | 
    #ifdef DEBUG  | 
    ||
286  | 
    void  | 
    ||
287  | 
    smi_debug_elements(struct ber_element *root)  | 
    ||
288  | 
    { | 
    ||
289  | 
    static int indent = 0;  | 
    ||
290  | 
    char *value;  | 
    ||
291  | 
    int constructed;  | 
    ||
292  | 
    |||
293  | 
    /* calculate lengths */  | 
    ||
294  | 
    ber_calc_len(root);  | 
    ||
295  | 
    |||
296  | 
    	switch (root->be_encoding) { | 
    ||
297  | 
    case BER_TYPE_SEQUENCE:  | 
    ||
298  | 
    case BER_TYPE_SET:  | 
    ||
299  | 
    constructed = root->be_encoding;  | 
    ||
300  | 
    break;  | 
    ||
301  | 
    default:  | 
    ||
302  | 
    constructed = 0;  | 
    ||
303  | 
    break;  | 
    ||
304  | 
    }  | 
    ||
305  | 
    |||
306  | 
    fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);  | 
    ||
307  | 
    	switch (root->be_class) { | 
    ||
308  | 
    case BER_CLASS_UNIVERSAL:  | 
    ||
309  | 
    fprintf(stderr, "class: universal(%u) type: ", root->be_class);  | 
    ||
310  | 
    		switch (root->be_type) { | 
    ||
311  | 
    case BER_TYPE_EOC:  | 
    ||
312  | 
    fprintf(stderr, "end-of-content");  | 
    ||
313  | 
    break;  | 
    ||
314  | 
    case BER_TYPE_BOOLEAN:  | 
    ||
315  | 
    fprintf(stderr, "boolean");  | 
    ||
316  | 
    break;  | 
    ||
317  | 
    case BER_TYPE_INTEGER:  | 
    ||
318  | 
    fprintf(stderr, "integer");  | 
    ||
319  | 
    break;  | 
    ||
320  | 
    case BER_TYPE_BITSTRING:  | 
    ||
321  | 
    fprintf(stderr, "bit-string");  | 
    ||
322  | 
    break;  | 
    ||
323  | 
    case BER_TYPE_OCTETSTRING:  | 
    ||
324  | 
    fprintf(stderr, "octet-string");  | 
    ||
325  | 
    break;  | 
    ||
326  | 
    case BER_TYPE_NULL:  | 
    ||
327  | 
    fprintf(stderr, "null");  | 
    ||
328  | 
    break;  | 
    ||
329  | 
    case BER_TYPE_OBJECT:  | 
    ||
330  | 
    fprintf(stderr, "object");  | 
    ||
331  | 
    break;  | 
    ||
332  | 
    case BER_TYPE_ENUMERATED:  | 
    ||
333  | 
    fprintf(stderr, "enumerated");  | 
    ||
334  | 
    break;  | 
    ||
335  | 
    case BER_TYPE_SEQUENCE:  | 
    ||
336  | 
    fprintf(stderr, "sequence");  | 
    ||
337  | 
    break;  | 
    ||
338  | 
    case BER_TYPE_SET:  | 
    ||
339  | 
    fprintf(stderr, "set");  | 
    ||
340  | 
    break;  | 
    ||
341  | 
    }  | 
    ||
342  | 
    break;  | 
    ||
343  | 
    case BER_CLASS_APPLICATION:  | 
    ||
344  | 
    fprintf(stderr, "class: application(%u) type: ",  | 
    ||
345  | 
    root->be_class);  | 
    ||
346  | 
    		switch (root->be_type) { | 
    ||
347  | 
    case SNMP_T_IPADDR:  | 
    ||
348  | 
    fprintf(stderr, "ipaddr");  | 
    ||
349  | 
    break;  | 
    ||
350  | 
    case SNMP_T_COUNTER32:  | 
    ||
351  | 
    fprintf(stderr, "counter32");  | 
    ||
352  | 
    break;  | 
    ||
353  | 
    case SNMP_T_GAUGE32:  | 
    ||
354  | 
    fprintf(stderr, "gauge32");  | 
    ||
355  | 
    break;  | 
    ||
356  | 
    case SNMP_T_TIMETICKS:  | 
    ||
357  | 
    fprintf(stderr, "timeticks");  | 
    ||
358  | 
    break;  | 
    ||
359  | 
    case SNMP_T_OPAQUE:  | 
    ||
360  | 
    fprintf(stderr, "opaque");  | 
    ||
361  | 
    break;  | 
    ||
362  | 
    case SNMP_T_COUNTER64:  | 
    ||
363  | 
    fprintf(stderr, "counter64");  | 
    ||
364  | 
    break;  | 
    ||
365  | 
    }  | 
    ||
366  | 
    break;  | 
    ||
367  | 
    case BER_CLASS_CONTEXT:  | 
    ||
368  | 
    fprintf(stderr, "class: context(%u) type: ",  | 
    ||
369  | 
    root->be_class);  | 
    ||
370  | 
    		switch (root->be_type) { | 
    ||
371  | 
    case SNMP_C_GETREQ:  | 
    ||
372  | 
    fprintf(stderr, "getreq");  | 
    ||
373  | 
    break;  | 
    ||
374  | 
    case SNMP_C_GETNEXTREQ:  | 
    ||
375  | 
    fprintf(stderr, "nextreq");  | 
    ||
376  | 
    break;  | 
    ||
377  | 
    case SNMP_C_GETRESP:  | 
    ||
378  | 
    fprintf(stderr, "getresp");  | 
    ||
379  | 
    break;  | 
    ||
380  | 
    case SNMP_C_SETREQ:  | 
    ||
381  | 
    fprintf(stderr, "setreq");  | 
    ||
382  | 
    break;  | 
    ||
383  | 
    case SNMP_C_TRAP:  | 
    ||
384  | 
    fprintf(stderr, "trap");  | 
    ||
385  | 
    break;  | 
    ||
386  | 
    case SNMP_C_GETBULKREQ:  | 
    ||
387  | 
    fprintf(stderr, "getbulkreq");  | 
    ||
388  | 
    break;  | 
    ||
389  | 
    case SNMP_C_INFORMREQ:  | 
    ||
390  | 
    fprintf(stderr, "informreq");  | 
    ||
391  | 
    break;  | 
    ||
392  | 
    case SNMP_C_TRAPV2:  | 
    ||
393  | 
    fprintf(stderr, "trapv2");  | 
    ||
394  | 
    break;  | 
    ||
395  | 
    case SNMP_C_REPORT:  | 
    ||
396  | 
    fprintf(stderr, "report");  | 
    ||
397  | 
    break;  | 
    ||
398  | 
    }  | 
    ||
399  | 
    break;  | 
    ||
400  | 
    case BER_CLASS_PRIVATE:  | 
    ||
401  | 
    fprintf(stderr, "class: private(%u) type: ", root->be_class);  | 
    ||
402  | 
    break;  | 
    ||
403  | 
    default:  | 
    ||
404  | 
    fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);  | 
    ||
405  | 
    break;  | 
    ||
406  | 
    }  | 
    ||
407  | 
    fprintf(stderr, "(%lu) encoding %lu ",  | 
    ||
408  | 
    root->be_type, root->be_encoding);  | 
    ||
409  | 
    |||
410  | 
    if ((value = smi_print_element(root)) == NULL)  | 
    ||
411  | 
    goto invalid;  | 
    ||
412  | 
    |||
413  | 
    	switch (root->be_encoding) { | 
    ||
414  | 
    case BER_TYPE_BOOLEAN:  | 
    ||
415  | 
    fprintf(stderr, "%s", value);  | 
    ||
416  | 
    break;  | 
    ||
417  | 
    case BER_TYPE_INTEGER:  | 
    ||
418  | 
    case BER_TYPE_ENUMERATED:  | 
    ||
419  | 
    fprintf(stderr, "value %s", value);  | 
    ||
420  | 
    break;  | 
    ||
421  | 
    case BER_TYPE_BITSTRING:  | 
    ||
422  | 
    fprintf(stderr, "hexdump %s", value);  | 
    ||
423  | 
    break;  | 
    ||
424  | 
    case BER_TYPE_OBJECT:  | 
    ||
425  | 
    fprintf(stderr, "oid %s", value);  | 
    ||
426  | 
    break;  | 
    ||
427  | 
    case BER_TYPE_OCTETSTRING:  | 
    ||
428  | 
    if (root->be_class == BER_CLASS_APPLICATION &&  | 
    ||
429  | 
    		    root->be_type == SNMP_T_IPADDR) { | 
    ||
430  | 
    fprintf(stderr, "addr %s", value);  | 
    ||
431  | 
    		} else { | 
    ||
432  | 
    fprintf(stderr, "string %s", value);  | 
    ||
433  | 
    }  | 
    ||
434  | 
    break;  | 
    ||
435  | 
    case BER_TYPE_NULL: /* no payload */  | 
    ||
436  | 
    case BER_TYPE_EOC:  | 
    ||
437  | 
    case BER_TYPE_SEQUENCE:  | 
    ||
438  | 
    case BER_TYPE_SET:  | 
    ||
439  | 
    default:  | 
    ||
440  | 
    fprintf(stderr, "%s", value);  | 
    ||
441  | 
    break;  | 
    ||
442  | 
    }  | 
    ||
443  | 
    |||
444  | 
    invalid:  | 
    ||
445  | 
    if (value == NULL)  | 
    ||
446  | 
    fprintf(stderr, "<INVALID>");  | 
    ||
447  | 
    else  | 
    ||
448  | 
    free(value);  | 
    ||
449  | 
    fprintf(stderr, "\n");  | 
    ||
450  | 
    |||
451  | 
    if (constructed)  | 
    ||
452  | 
    root->be_encoding = constructed;  | 
    ||
453  | 
    |||
454  | 
    	if (constructed && root->be_sub) { | 
    ||
455  | 
    indent += 2;  | 
    ||
456  | 
    smi_debug_elements(root->be_sub);  | 
    ||
457  | 
    indent -= 2;  | 
    ||
458  | 
    }  | 
    ||
459  | 
    if (root->be_next)  | 
    ||
460  | 
    smi_debug_elements(root->be_next);  | 
    ||
461  | 
    }  | 
    ||
462  | 
    #endif  | 
    ||
463  | 
    |||
464  | 
    char *  | 
    ||
465  | 
    smi_print_element(struct ber_element *root)  | 
    ||
466  | 
    { | 
    ||
467  | 
    char *str = NULL, *buf, *p;  | 
    ||
468  | 
    size_t len, i;  | 
    ||
469  | 
    long long v;  | 
    ||
470  | 
    int d;  | 
    ||
471  | 
    struct ber_oid o;  | 
    ||
472  | 
    char strbuf[BUFSIZ];  | 
    ||
473  | 
    |||
474  | 
    	switch (root->be_encoding) { | 
    ||
475  | 
    case BER_TYPE_BOOLEAN:  | 
    ||
476  | 
    if (ber_get_boolean(root, &d) == -1)  | 
    ||
477  | 
    goto fail;  | 
    ||
478  | 
    if (asprintf(&str, "%s(%d)", d ? "true" : "false", d) == -1)  | 
    ||
479  | 
    goto fail;  | 
    ||
480  | 
    break;  | 
    ||
481  | 
    case BER_TYPE_INTEGER:  | 
    ||
482  | 
    case BER_TYPE_ENUMERATED:  | 
    ||
483  | 
    if (ber_get_integer(root, &v) == -1)  | 
    ||
484  | 
    goto fail;  | 
    ||
485  | 
    if (asprintf(&str, "%lld", v) == -1)  | 
    ||
486  | 
    goto fail;  | 
    ||
487  | 
    break;  | 
    ||
488  | 
    case BER_TYPE_BITSTRING:  | 
    ||
489  | 
    if (ber_get_bitstring(root, (void *)&buf, &len) == -1)  | 
    ||
490  | 
    goto fail;  | 
    ||
491  | 
    if ((str = calloc(1, len * 2 + 1)) == NULL)  | 
    ||
492  | 
    goto fail;  | 
    ||
493  | 
    		for (p = str, i = 0; i < len; i++) { | 
    ||
494  | 
    snprintf(p, 3, "%02x", buf[i]);  | 
    ||
495  | 
    p += 2;  | 
    ||
496  | 
    }  | 
    ||
497  | 
    break;  | 
    ||
498  | 
    case BER_TYPE_OBJECT:  | 
    ||
499  | 
    if (ber_get_oid(root, &o) == -1)  | 
    ||
500  | 
    goto fail;  | 
    ||
501  | 
    if (asprintf(&str, "%s",  | 
    ||
502  | 
    smi_oid2string(&o, strbuf, sizeof(strbuf), 0)) == -1)  | 
    ||
503  | 
    goto fail;  | 
    ||
504  | 
    break;  | 
    ||
505  | 
    case BER_TYPE_OCTETSTRING:  | 
    ||
506  | 
    if (ber_get_string(root, &buf) == -1)  | 
    ||
507  | 
    goto fail;  | 
    ||
508  | 
    if (root->be_class == BER_CLASS_APPLICATION &&  | 
    ||
509  | 
    		    root->be_type == SNMP_T_IPADDR) { | 
    ||
510  | 
    if (asprintf(&str, "%s",  | 
    ||
511  | 
    inet_ntoa(*(struct in_addr *)buf)) == -1)  | 
    ||
512  | 
    goto fail;  | 
    ||
513  | 
    		} else { | 
    ||
514  | 
    if ((p = reallocarray(NULL, 4, root->be_len + 1)) == NULL)  | 
    ||
515  | 
    goto fail;  | 
    ||
516  | 
    strvisx(p, buf, root->be_len, VIS_NL);  | 
    ||
517  | 
    			if (asprintf(&str, "\"%s\"", p) == -1) { | 
    ||
518  | 
    free(p);  | 
    ||
519  | 
    goto fail;  | 
    ||
520  | 
    }  | 
    ||
521  | 
    free(p);  | 
    ||
522  | 
    }  | 
    ||
523  | 
    break;  | 
    ||
524  | 
    case BER_TYPE_NULL: /* no payload */  | 
    ||
525  | 
    case BER_TYPE_EOC:  | 
    ||
526  | 
    case BER_TYPE_SEQUENCE:  | 
    ||
527  | 
    case BER_TYPE_SET:  | 
    ||
528  | 
    default:  | 
    ||
529  | 
    		str = strdup(""); | 
    ||
530  | 
    break;  | 
    ||
531  | 
    }  | 
    ||
532  | 
    |||
533  | 
    return (str);  | 
    ||
534  | 
    |||
535  | 
    fail:  | 
    ||
536  | 
    free(str);  | 
    ||
537  | 
    return (NULL);  | 
    ||
538  | 
    }  | 
    ||
539  | 
    |||
540  | 
    unsigned long  | 
    ||
541  | 
    smi_application(struct ber_element *elm)  | 
    ||
542  | 
    { | 
    ||
543  | 
    if (elm->be_class != BER_CLASS_APPLICATION)  | 
    ||
544  | 
    return (BER_TYPE_OCTETSTRING);  | 
    ||
545  | 
    |||
546  | 
    	switch (elm->be_type) { | 
    ||
547  | 
    case SNMP_T_IPADDR:  | 
    ||
548  | 
    return (BER_TYPE_OCTETSTRING);  | 
    ||
549  | 
    case SNMP_T_COUNTER32:  | 
    ||
550  | 
    case SNMP_T_GAUGE32:  | 
    ||
551  | 
    case SNMP_T_TIMETICKS:  | 
    ||
552  | 
    case SNMP_T_OPAQUE:  | 
    ||
553  | 
    case SNMP_T_COUNTER64:  | 
    ||
554  | 
    return (BER_TYPE_INTEGER);  | 
    ||
555  | 
    default:  | 
    ||
556  | 
    break;  | 
    ||
557  | 
    }  | 
    ||
558  | 
    return (BER_TYPE_OCTETSTRING);  | 
    ||
559  | 
    }  | 
    ||
560  | 
    |||
561  | 
    int  | 
    ||
562  | 
    smi_oid_cmp(struct oid *a, struct oid *b)  | 
    ||
563  | 
    { | 
    ||
564  | 
    size_t i;  | 
    ||
565  | 
    |||
566  | 
    ✓✓ | 464876  | 
    for (i = 0; i < MINIMUM(a->o_oidlen, b->o_oidlen); i++)  | 
    
567  | 
    ✓✓ | 216204  | 
    if (a->o_oid[i] != b->o_oid[i])  | 
    
568  | 
    26360  | 
    return (a->o_oid[i] - b->o_oid[i]);  | 
    |
569  | 
    |||
570  | 
    /*  | 
    ||
571  | 
    * Return success if the matched object is a table  | 
    ||
572  | 
    * or a MIB registered by a subagent  | 
    ||
573  | 
    * (it will match any sub-elements)  | 
    ||
574  | 
    */  | 
    ||
575  | 
    ✓✗✗✗ | 
    2036  | 
    if ((b->o_flags & OID_TABLE ||  | 
    
576  | 
    ✗✓ | 2036  | 
    b->o_flags & OID_REGISTERED) &&  | 
    
577  | 
    (a->o_flags & OID_KEY) == 0 &&  | 
    ||
578  | 
    (a->o_oidlen > b->o_oidlen))  | 
    ||
579  | 
    return (0);  | 
    ||
580  | 
    |||
581  | 
    2036  | 
    return (a->o_oidlen - b->o_oidlen);  | 
    |
582  | 
    28396  | 
    }  | 
    |
583  | 
    |||
584  | 
    ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✓ ✓✓✓✗ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✗✓✓ ✓✗✓✓ ✓✓✓✓ ✓✓✓✗ ✓✓✓✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗  | 
    174540  | 
    RB_GENERATE(oidtree, oid, o_element, smi_oid_cmp);  | 
    
585  | 
    |||
586  | 
    int  | 
    ||
587  | 
    smi_key_cmp(struct oid *a, struct oid *b)  | 
    ||
588  | 
    { | 
    ||
589  | 
    ✓✗✗✓ | 
    65364  | 
    if (a->o_name == NULL || b->o_name == NULL)  | 
    
590  | 
    return (-1);  | 
    ||
591  | 
    21788  | 
    return (strcasecmp(a->o_name, b->o_name));  | 
    |
592  | 
    21788  | 
    }  | 
    |
593  | 
    |||
594  | 
    ✓✓✓✓ ✓✗✓✓ ✗✗✗✗ ✗✗✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✗✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✗ ✓✓✓✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗  | 
    126940  | 
    RB_GENERATE(keytree, oid, o_keyword, smi_key_cmp);  | 
    
| Generated by: GCOVR (Version 3.3) |