xref: /openbsd/usr.sbin/snmpd/smi.c (revision 404b540a)
1 /*	$OpenBSD: smi.c,v 1.5 2008/01/16 09:51:15 reyk Exp $	*/
2 
3 /*
4  * Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net>
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/param.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <sys/tree.h>
26 #include <sys/sysctl.h>
27 
28 #include <net/if.h>
29 #include <net/if_dl.h>
30 #include <net/if_arp.h>
31 #include <net/if_media.h>
32 #include <net/route.h>
33 #include <netinet/in.h>
34 #include <netinet/if_ether.h>
35 #include <arpa/inet.h>
36 
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <errno.h>
40 #include <event.h>
41 #include <fcntl.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <pwd.h>
45 
46 #include "snmpd.h"
47 #include "mib.h"
48 
49 extern struct snmpd *env;
50 
51 RB_HEAD(oidtree, oid);
52 RB_PROTOTYPE(oidtree, oid, o_element, smi_oid_cmp);
53 struct oidtree smi_oidtree;
54 
55 u_long
56 smi_getticks(void)
57 {
58 	struct timeval	 now, run;
59 	u_long		 ticks;
60 
61 	gettimeofday(&now, NULL);
62 	if (timercmp(&now, &env->sc_starttime, <=))
63 		return (0);
64 	timersub(&now, &env->sc_starttime, &run);
65 	ticks = run.tv_sec * 100;
66 	if (run.tv_usec)
67 		ticks += run.tv_usec / 10000;
68 
69 	return (ticks);
70 }
71 
72 void
73 smi_oidlen(struct ber_oid *o)
74 {
75 	size_t	 i;
76 	for (i = 0; i < BER_MAX_OID_LEN && o->bo_id[i] != 0; i++);
77 	o->bo_n = i;
78 }
79 
80 char *
81 smi_oidstring(struct ber_oid *o, char *buf, size_t len)
82 {
83 	char		 str[256];
84 	struct oid	*value, key;
85 	size_t		 i, lookup = 1;
86 
87 	bzero(buf, len);
88 	bzero(&key, sizeof(key));
89 	bcopy(o, &key.o_id, sizeof(struct ber_oid));
90 	key.o_flags |= OID_KEY;		/* do not match wildcards */
91 
92 	if (env->sc_flags & SNMPD_F_NONAMES)
93 		lookup = 0;
94 
95 	for (i = 0; i < o->bo_n; i++) {
96 		key.o_oidlen = i + 1;
97 		if (lookup &&
98 		    (value = RB_FIND(oidtree, &smi_oidtree, &key)) != NULL)
99 			snprintf(str, sizeof(str), "%s", value->o_name);
100 		else
101 			snprintf(str, sizeof(str), "%d", key.o_oid[i]);
102 		strlcat(buf, str, len);
103 		if (i < (o->bo_n - 1))
104 			strlcat(buf, ".", len);
105 	}
106 
107 	return (buf);
108 }
109 
110 void
111 smi_delete(struct oid *oid)
112 {
113 	struct oid	 key, *value;
114 
115 	bcopy(&oid->o_id, &key.o_id, sizeof(struct ber_oid));
116 	if ((value = RB_FIND(oidtree, &smi_oidtree, &key)) != NULL &&
117 	    value == oid)
118 		RB_REMOVE(oidtree, &smi_oidtree, value);
119 
120 	if (oid->o_data != NULL)
121 		free(oid->o_data);
122 	if (oid->o_flags & OID_DYNAMIC) {
123 		free(oid->o_name);
124 		free(oid);
125 	}
126 }
127 
128 void
129 smi_insert(struct oid *oid)
130 {
131 	struct oid		 key, *value;
132 
133 	if ((oid->o_flags & OID_TABLE) && oid->o_get == NULL)
134 		fatalx("smi_insert: invalid MIB table");
135 
136 	bcopy(&oid->o_id, &key.o_id, sizeof(struct ber_oid));
137 	value = RB_FIND(oidtree, &smi_oidtree, &key);
138 	if (value != NULL)
139 		smi_delete(value);
140 
141 	RB_INSERT(oidtree, &smi_oidtree, oid);
142 }
143 
144 void
145 smi_mibtree(struct oid *oids)
146 {
147 	struct oid	*oid, *decl;
148 	size_t		 i;
149 
150 	for (i = 0; oids[i].o_oid[0] != 0; i++) {
151 		oid = &oids[i];
152 		smi_oidlen(&oid->o_id);
153 		if (oid->o_name != NULL) {
154 			if ((oid->o_flags & OID_TABLE) && oid->o_get == NULL)
155 				fatalx("smi_mibtree: invalid MIB table");
156 			RB_INSERT(oidtree, &smi_oidtree, oid);
157 			continue;
158 		}
159 		decl = RB_FIND(oidtree, &smi_oidtree, oid);
160 		if (decl == NULL)
161 			fatalx("smi_mibtree: undeclared MIB");
162 		decl->o_flags = oid->o_flags;
163 		decl->o_get = oid->o_get;
164 		decl->o_set = oid->o_set;
165 		decl->o_table = oid->o_table;
166 		decl->o_val = oid->o_val;
167 		decl->o_data = oid->o_data;
168 	}
169 }
170 
171 int
172 smi_init(void)
173 {
174 	RB_INIT(&smi_oidtree);
175 	mib_init();
176 	return (0);
177 }
178 
179 struct oid *
180 smi_find(struct oid *oid)
181 {
182 	return (RB_FIND(oidtree, &smi_oidtree, oid));
183 }
184 
185 struct oid *
186 smi_next(struct oid *oid)
187 {
188 	return (RB_NEXT(oidtree, &smi_oidtree, oid));
189 }
190 
191 struct oid *
192 smi_foreach(struct oid *oid, u_int flags)
193 {
194 	/*
195 	 * Traverse the tree of MIBs with the option to check
196 	 * for specific OID flags.
197 	 */
198 	if (oid == NULL) {
199 		oid = RB_MIN(oidtree, &smi_oidtree);
200 		if (oid == NULL)
201 			return (NULL);
202 		if (flags == 0 || (oid->o_flags & flags))
203 			return (oid);
204 	}
205 	for (;;) {
206 		oid = RB_NEXT(oidtree, &smi_oidtree, oid);
207 		if (oid == NULL)
208 			break;
209 		if (flags == 0 || (oid->o_flags & flags))
210 			return (oid);
211 	}
212 
213 	return (oid);
214 }
215 
216 int
217 smi_oid_cmp(struct oid *a, struct oid *b)
218 {
219 	size_t	 i;
220 
221 	for (i = 0; i < MIN(a->o_oidlen, b->o_oidlen); i++)
222 		if (a->o_oid[i] != b->o_oid[i])
223 			return (a->o_oid[i] - b->o_oid[i]);
224 
225 	/*
226 	 * Return success if the matched object is a table
227 	 * (it will match any sub-elements)
228 	 */
229 	if ((b->o_flags & OID_TABLE) &&
230 	    (a->o_flags & OID_KEY) == 0 &&
231 	    (a->o_oidlen > b->o_oidlen))
232 		return (0);
233 
234 	return (a->o_oidlen - b->o_oidlen);
235 }
236 
237 RB_GENERATE(oidtree, oid, o_element, smi_oid_cmp);
238