xref: /openbsd-src/regress/lib/libagentx/main.c (revision c29afb189edb5b54d648e9ab72122da2b1c5e81d)
1 /*	$OpenBSD: main.c,v 1.7 2021/05/01 16:55:14 martijn Exp $	*/
2 
3 /*
4  * Copyright (c) 2019 Martijn van Duren <martijn@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/socket.h>
20 #include <sys/types.h>
21 #include <sys/un.h>
22 
23 #include <arpa/inet.h>
24 
25 #include <event.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 
32 #include "log.h"
33 #include <agentx.h>
34 
35 #define LINKDOWN 1, 3, 6, 1, 6, 3, 1, 1, 5, 3
36 #define IFINDEX 1, 3, 6, 1, 2, 1, 2, 2, 1, 1
37 #define IFADMINSTATUS 1, 3, 6, 1, 2, 1, 2, 2, 1, 7
38 #define IFOPERSTATUS 1, 3, 6, 1, 2, 1, 2, 2, 1, 8
39 
40 void regress_fd(struct agentx *, void *, int);
41 void regress_tryconnect(int, short, void *);
42 void regress_read(int, short, void *);
43 void regress_usr1(int, short, void *);
44 void regress_usr2(int, short, void *);
45 void regress_scalarinteger(struct agentx_varbind *);
46 void regress_scalarstring(struct agentx_varbind *);
47 void regress_scalarnull(struct agentx_varbind *);
48 void regress_scalaroid(struct agentx_varbind *);
49 void regress_scalaripaddress(struct agentx_varbind *);
50 void regress_scalarcounter32(struct agentx_varbind *);
51 void regress_scalargauge32(struct agentx_varbind *);
52 void regress_scalartimeticks(struct agentx_varbind *);
53 void regress_scalaropaque(struct agentx_varbind *);
54 void regress_scalarcounter64(struct agentx_varbind *);
55 void regress_scalarerror(struct agentx_varbind *);
56 
57 void regress_intindex(struct agentx_varbind *);
58 void regress_intindex2(struct agentx_varbind *);
59 
60 void regress_strindex(struct agentx_varbind *);
61 void regress_implstrindex(struct agentx_varbind *);
62 void regress_strindex2(struct agentx_varbind *);
63 
64 void regress_oidimplindex(struct agentx_varbind *);
65 
66 void regress_ipaddressindex(struct agentx_varbind *);
67 
68 void regress_intindexstaticvalueint(struct agentx_varbind *);
69 void regress_intindexstaticvaluestring(struct agentx_varbind *);
70 void regress_intindexstaticanyint(struct agentx_varbind *);
71 void regress_intindexstaticanystring(struct agentx_varbind *);
72 void regress_intindexstaticnewint(struct agentx_varbind *);
73 void regress_intindexstaticnewstring(struct agentx_varbind *);
74 
75 struct agentx *sa;
76 struct agentx_session *sas;
77 struct agentx_context *sac;
78 struct agentx_agentcaps *saa;
79 struct agentx_region *regress;
80 
81 struct agentx_index *regressidx_int;
82 struct agentx_index *regressidx_int2;
83 
84 struct agentx_index *regressidx_str;
85 struct agentx_index *regressidx_str2;
86 
87 struct agentx_index *regressidx_oid;
88 
89 struct agentx_index *regressidx_ipaddress;
90 
91 struct agentx_index *regressidx_new;
92 struct agentx_index *regressidx_any;
93 struct agentx_index *regressidx_value;
94 
95 struct agentx_object *regressobj_scalarinteger;
96 struct agentx_object *regressobj_scalarstring;
97 struct agentx_object *regressobj_scalarnull;
98 struct agentx_object *regressobj_scalaroid;
99 struct agentx_object *regressobj_scalaripaddress;
100 struct agentx_object *regressobj_scalarcounter32;
101 struct agentx_object *regressobj_scalargauge32;
102 struct agentx_object *regressobj_scalartimeticks;
103 struct agentx_object *regressobj_scalaropaque;
104 struct agentx_object *regressobj_scalarcounter64;
105 
106 struct agentx_object *regressobj_intindexint;
107 struct agentx_object *regressobj_intindexint2;
108 
109 struct agentx_object *regressobj_strindexstr;
110 struct agentx_object *regressobj_implstrindexstr;
111 struct agentx_object *regressobj_strindexstr2;
112 
113 struct agentx_object *regressobj_oidimplindexoid;
114 
115 struct agentx_object *regressobj_ipaddressindexipaddress;
116 
117 struct agentx_object *regressobj_intindexstaticvalueint;
118 struct agentx_object *regressobj_intindexstaticvaluestring;
119 struct agentx_object *regressobj_intindexstaticanyint;
120 struct agentx_object *regressobj_intindexstaticanystring;
121 struct agentx_object *regressobj_intindexstaticnewint;
122 struct agentx_object *regressobj_intindexstaticnewstring;
123 
124 struct agentx_object *regressobj_scalarerror;
125 
126 char *path = AGENTX_MASTER_PATH;
127 int fd = -1;
128 struct event rev;
129 struct event intev, usr1ev, usr2ev, connev;
130 
131 int
main(int argc,char * argv[])132 main(int argc, char *argv[])
133 {
134 	struct agentx_index *idx[AGENTX_OID_INDEX_MAX_LEN];
135 	int ch;
136 	int dflag = 0;
137 
138 	log_init(2, 1);
139 
140 	while ((ch = getopt(argc, argv, "d")) != -1) {
141 		switch (ch) {
142 		case 'd':
143 			dflag = 1;
144 			break;
145 		default:
146 			exit(1);
147 		}
148 	}
149 
150 	argc -= optind;
151 	argv += optind;
152 
153 	if (argc >= 1)
154 		path = argv[0];
155 
156 	bzero(&rev, sizeof(rev));
157 
158 	agentx_log_fatal = fatalx;
159 	agentx_log_warn = log_warnx;
160 	agentx_log_info = log_info;
161 	agentx_log_debug = log_debug;
162 
163 	if ((sa = agentx(regress_fd, (void *)path)) == NULL)
164 		fatal("agentx");
165 	sas = agentx_session(sa, NULL, 0, "OpenAgentX regress", 0);
166 	if (sas == NULL)
167 		fatal("agentx_session");
168 	if ((sac = agentx_context(sas, NULL)) == NULL)
169 		fatal("agentx_context");
170 	if ((saa = agentx_agentcaps(sac,
171 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 50, 1),
172 	    "OpenBSD AgentX regress")) == NULL)
173 		fatal("agentx_agentcaps");
174 	if ((regress = agentx_region(sac,
175 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100), 0)) == NULL)
176 		fatal("agentx_region application");
177 	if ((regressobj_scalarinteger = agentx_object(regress,
178 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 1), NULL, 0,
179 	    0, regress_scalarinteger)) == NULL)
180 		fatal("agentx_object");
181 	if ((regressobj_scalarstring = agentx_object(regress,
182 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 2), NULL, 0,
183 	    0, regress_scalarstring)) == NULL)
184 		fatal("agentx_object");
185 /* netsnmp doesn't return NULL-objects */
186 /*
187 	if ((regressobj_scalarnull = agentx_object(regress,
188 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 3), NULL, 0,
189 	    0, regress_scalarnull)) == NULL)
190 		fatal("agentx_object");
191 */
192 	if ((regressobj_scalaroid = agentx_object(regress,
193 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 4), NULL, 0,
194 	    0, regress_scalaroid)) == NULL)
195 		fatal("agentx_object");
196 	if ((regressobj_scalaripaddress = agentx_object(regress,
197 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 5), NULL, 0,
198 	    0, regress_scalaripaddress)) == NULL)
199 		fatal("agentx_object");
200 	if ((regressobj_scalarcounter32 = agentx_object(regress,
201 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 6), NULL, 0,
202 	    0, regress_scalarcounter32)) == NULL)
203 		fatal("agentx_object");
204 	if ((regressobj_scalargauge32 = agentx_object(regress,
205 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 7), NULL, 0,
206 	    0, regress_scalargauge32)) == NULL)
207 		fatal("agentx_object");
208 	if ((regressobj_scalartimeticks = agentx_object(regress,
209 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 8), NULL, 0,
210 	    0, regress_scalartimeticks)) == NULL)
211 		fatal("agentx_object");
212 	if ((regressobj_scalaropaque = agentx_object(regress,
213 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 9), NULL, 0,
214 	    0, regress_scalaropaque)) == NULL)
215 		fatal("agentx_object");
216 	if ((regressobj_scalarcounter64 = agentx_object(regress,
217 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 10), NULL, 0,
218 	    0, regress_scalarcounter64)) == NULL)
219 		fatal("agentx_object");
220 
221 	if ((regressidx_int = agentx_index_integer_dynamic(regress,
222 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 11, 1, 1))) == NULL)
223 		fatal("agentx_index_integer_dynamic");
224 	if ((regressobj_intindexint = agentx_object(regress,
225 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 11, 1, 1),
226 	    &regressidx_int, 1, 0, regress_intindex)) == NULL)
227 		fatal("agentx_object");
228 
229 	if ((regressidx_int2 = agentx_index_integer_dynamic(regress,
230 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 12, 1, 1))) == NULL)
231 		fatal("agentx_index_integer_dynamic");
232 	idx[0] = regressidx_int;
233 	idx[1] = regressidx_int2;
234 	if ((regressobj_intindexint2 = agentx_object(regress,
235 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 12, 1, 1),
236 	    idx, 2, 0, regress_intindex2)) == NULL)
237 		fatal("agentx_object");
238 
239 	if ((regressidx_str = agentx_index_string_dynamic(regress,
240 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 13, 1, 1))) == NULL)
241 		fatal("agentx_index_string_dynamic");
242 	if ((regressobj_strindexstr = agentx_object(regress,
243 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 13, 1, 1),
244 	    &regressidx_str, 1, 0, regress_strindex)) == NULL)
245 		fatal("agentx_object");
246 	if ((regressobj_implstrindexstr = agentx_object(regress,
247 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 14, 1, 1),
248 	    &regressidx_str, 1, 1, regress_implstrindex)) == NULL)
249 		fatal("agentx_object");
250 	if ((regressidx_str2 = agentx_index_string_dynamic(regress,
251 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 15, 1, 1))) == NULL)
252 		fatal("agentx_index_string_dynamic");
253 	idx[0] = regressidx_str;
254 	idx[1] = regressidx_str2;
255 	if ((regressobj_strindexstr = agentx_object(regress,
256 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 15, 1, 1),
257 	    idx, 2, 0, regress_strindex2)) == NULL)
258 		fatal("agentx_object");
259 
260 	if ((regressidx_oid = agentx_index_oid_dynamic(regress,
261 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 16, 1, 1))) == NULL)
262 		fatal("agentx_index_oid_dynamic");
263 	if ((regressobj_oidimplindexoid = agentx_object(regress,
264 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 16, 1, 1),
265 	    &regressidx_oid, 1, 1, regress_oidimplindex)) == NULL)
266 		fatal("agentx_object");
267 
268 	if ((regressidx_ipaddress = agentx_index_ipaddress_dynamic(regress,
269 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 17, 1, 1))) == NULL)
270 		fatal("agentx_index_oid_dynamic");
271 	if ((regressobj_oidimplindexoid = agentx_object(regress,
272 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 17, 1, 1),
273 	    &regressidx_ipaddress, 1, 0, regress_ipaddressindex)) == NULL)
274 		fatal("agentx_object");
275 
276 	if ((regressidx_value = agentx_index_integer_value(regress,
277 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 18, 1, 1), 5)) == NULL)
278 		fatal("agentx_index_oid_dynamic");
279 	if ((regressobj_intindexstaticvalueint = agentx_object(regress,
280 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 18, 1, 1),
281 	    &regressidx_value, 1, 0, regress_intindexstaticvalueint)) == NULL)
282 		fatal("agentx_object");
283 	if ((regressobj_intindexstaticvaluestring = agentx_object(regress,
284 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 18, 1, 2),
285 	    &regressidx_value, 1, 0, regress_intindexstaticvaluestring)) == NULL)
286 		fatal("agentx_object");
287 
288 	if ((regressidx_any = agentx_index_integer_any(regress,
289 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 19, 1, 1))) == NULL)
290 		fatal("agentx_index_integer_any");
291 	if ((regressobj_intindexstaticanyint = agentx_object(regress,
292 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 19, 1, 1),
293 	    &regressidx_any, 1, 0, regress_intindexstaticanyint)) == NULL)
294 		fatal("agentx_object");
295 	if ((regressobj_intindexstaticanystring = agentx_object(regress,
296 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 19, 1, 2),
297 	    &regressidx_any, 1, 0, regress_intindexstaticanystring)) == NULL)
298 		fatal("agentx_object");
299 
300 	if ((regressidx_new = agentx_index_integer_new(regress,
301 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 20, 1, 1))) == NULL)
302 		fatal("agentx_index_integer_new");
303 	if ((regressobj_intindexstaticnewint = agentx_object(regress,
304 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 20, 1, 1),
305 	    &regressidx_new, 1, 0, regress_intindexstaticnewint)) == NULL)
306 		fatal("agentx_object");
307 	if ((regressobj_intindexstaticnewstring = agentx_object(regress,
308 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, 20, 1, 2),
309 	    &regressidx_new, 1, 0, regress_intindexstaticnewstring)) == NULL)
310 		fatal("agentx_object");
311 
312 	if ((regressobj_scalarerror = agentx_object(regress,
313 	    AGENTX_OID(AGENTX_ENTERPRISES, 30155, 100, UINT32_MAX), NULL,
314 	    0, 0, regress_scalarerror)) == NULL)
315 		fatal("agentx_object");
316 
317 	if (!dflag) {
318 		if (daemon(0, 1) == -1)
319 			fatalx("daemon");
320 	}
321 
322 	event_init();
323 
324 	event_set(&rev, fd, EV_READ|EV_PERSIST, regress_read, NULL);
325 	if (event_add(&rev, NULL) == -1)
326 		fatal("event_add");
327 
328 	event_dispatch();
329 	return 0;
330 }
331 
332 void
regress_fd(struct agentx * sa2,void * cookie,int close)333 regress_fd(struct agentx *sa2, void *cookie, int close)
334 {
335 	static int init = 0;
336 	struct sockaddr_un sun;
337 
338 	/* For ease of cleanup we take the single run approach */
339 	if (init) {
340 		if (!close)
341 			agentx_free(sa);
342 		else
343 			evtimer_del(&rev);
344 	} else {
345 		sun.sun_family = AF_UNIX;
346 		strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
347 
348 		if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ||
349 		    connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
350 			fatal("connect");
351 		}
352 		agentx_connect(sa2, fd);
353 		init = 1;
354 	}
355 }
356 
357 void
regress_read(int fd,short event,void * cookie)358 regress_read(int fd, short event, void *cookie)
359 {
360 	agentx_read(sa);
361 }
362 
363 #ifdef notyet
364 
365 void
regress_usr1(int fd,short event,void * cookie)366 regress_usr1(int fd, short event, void *cookie)
367 {
368 	struct agentx_notify *san;
369 
370 	if ((san = agentx_notify(sac, AGENTX_OID(LINKDOWN))) == NULL)
371 		fatal("agentx_notify");
372 
373 	agentx_notify_integer(san, AGENTX_OID(IFINDEX), 1);
374 	agentx_notify_integer(san, AGENTX_OID(IFADMINSTATUS), 3);
375 	agentx_notify_integer(san, AGENTX_OID(IFOPERSTATUS), 6);
376 	agentx_notify_send(san);
377 }
378 
379 #endif
380 
381 void
regress_usr2(int fd,short event,void * cookie)382 regress_usr2(int fd, short event, void *cookie)
383 {
384 }
385 
386 void
regress_scalarstring(struct agentx_varbind * vb)387 regress_scalarstring(struct agentx_varbind *vb)
388 {
389 	agentx_varbind_string(vb, "scalar-string");
390 }
391 
392 void
regress_scalarinteger(struct agentx_varbind * vb)393 regress_scalarinteger(struct agentx_varbind *vb)
394 {
395 	agentx_varbind_integer(vb, 1);
396 }
397 
398 void
regress_scalarnull(struct agentx_varbind * vb)399 regress_scalarnull(struct agentx_varbind *vb)
400 {
401 	agentx_varbind_null(vb);
402 }
403 
404 void
regress_scalaroid(struct agentx_varbind * vb)405 regress_scalaroid(struct agentx_varbind *vb)
406 {
407 	agentx_varbind_oid(vb, AGENTX_OID(AGENTX_ENTERPRISES, 30155));
408 }
409 
410 void
regress_scalaripaddress(struct agentx_varbind * vb)411 regress_scalaripaddress(struct agentx_varbind *vb)
412 {
413 	struct in_addr addr;
414 
415 	inet_aton("127.0.0.1", &addr);
416 
417 	agentx_varbind_ipaddress(vb, &addr);
418 }
419 
420 void
regress_scalarcounter32(struct agentx_varbind * vb)421 regress_scalarcounter32(struct agentx_varbind *vb)
422 {
423 	agentx_varbind_counter32(vb, 1);
424 }
425 
426 void
regress_scalargauge32(struct agentx_varbind * vb)427 regress_scalargauge32(struct agentx_varbind *vb)
428 {
429 	agentx_varbind_gauge32(vb, 1);
430 }
431 
432 void
regress_scalartimeticks(struct agentx_varbind * vb)433 regress_scalartimeticks(struct agentx_varbind *vb)
434 {
435 	agentx_varbind_timeticks(vb, 1);
436 }
437 
438 void
regress_scalaropaque(struct agentx_varbind * vb)439 regress_scalaropaque(struct agentx_varbind *vb)
440 {
441 	agentx_varbind_opaque(vb, "abc", 3);
442 }
443 
444 void
regress_scalarcounter64(struct agentx_varbind * vb)445 regress_scalarcounter64(struct agentx_varbind *vb)
446 {
447 	agentx_varbind_counter64(vb, 1);
448 }
449 
450 void
regress_intindex(struct agentx_varbind * vb)451 regress_intindex(struct agentx_varbind *vb)
452 {
453 	uint32_t idx;
454 
455 	idx = agentx_varbind_get_index_integer(vb, regressidx_int);
456 	switch (agentx_varbind_request(vb)) {
457 	case AGENTX_REQUEST_TYPE_GET:
458 		if (idx == 0) {
459 			agentx_varbind_notfound(vb);
460 			return;
461 		}
462 		break;
463 	case AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE:
464 		if (idx == 0)
465 			idx++;
466 		break;
467 	case AGENTX_REQUEST_TYPE_GETNEXT:
468 		idx++;
469 		break;
470 	}
471 	if (idx > 0xf)
472 		agentx_varbind_notfound(vb);
473 	else {
474 		agentx_varbind_set_index_integer(vb, regressidx_int, idx);
475 		agentx_varbind_integer(vb, idx);
476 	}
477 }
478 
479 void
regress_intindex2(struct agentx_varbind * vb)480 regress_intindex2(struct agentx_varbind *vb)
481 {
482 	uint32_t idx1, idx2;
483 	enum agentx_request_type type;
484 
485 	idx1 = agentx_varbind_get_index_integer(vb, regressidx_int);
486 	idx2 = agentx_varbind_get_index_integer(vb, regressidx_int2);
487 	type = agentx_varbind_request(vb);
488 	if (type == AGENTX_REQUEST_TYPE_GETNEXT)
489 		idx2++;
490 	if (type == AGENTX_REQUEST_TYPE_GETNEXT ||
491 	    type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) {
492 		if (idx2 > 1) {
493 			idx1++;
494 			idx2 = 0;
495 		}
496 	}
497 	if (idx2 > 1 || idx1 > 8)
498 		agentx_varbind_notfound(vb);
499 	else {
500 		agentx_varbind_set_index_integer(vb, regressidx_int, idx1);
501 		agentx_varbind_set_index_integer(vb, regressidx_int2, idx2);
502 		agentx_varbind_integer(vb, (idx1 << 1) + idx2);
503 	}
504 }
505 
506 void
regress_strindex(struct agentx_varbind * vb)507 regress_strindex(struct agentx_varbind *vb)
508 {
509 	const unsigned char *idx;
510 	size_t slen;
511 	int implied;
512 	enum agentx_request_type request = agentx_varbind_request(vb);
513 
514 	idx = agentx_varbind_get_index_string(vb, regressidx_str, &slen,
515 	    &implied);
516 
517 	if (implied)
518 		fatalx("%s: string length should not be implied", __func__);
519 
520 	if (slen == 0) {
521 		if (request == AGENTX_REQUEST_TYPE_GET) {
522 			log_warnx("%s: 0 index should be handled in agentx.c",
523 			    __func__);
524 			agentx_varbind_error(vb);
525 			return;
526 		}
527 	}
528 	/* !implied first needs a length check before content check */
529 	if (slen > 1) {
530 		agentx_varbind_notfound(vb);
531 		return;
532 	}
533 	if (request == AGENTX_REQUEST_TYPE_GETNEXT) {
534 		if (idx[0] == 'a')
535 			idx = (unsigned char *)"b";
536 		else if (idx[0] == 'b')
537 			idx = (unsigned char *)"c";
538 		else if (idx[0] >= 'c') {
539 			agentx_varbind_notfound(vb);
540 			return;
541 		}
542 	}
543 	if (idx == NULL || idx[0] < 'a') {
544 		if (request == AGENTX_REQUEST_TYPE_GET) {
545 			agentx_varbind_notfound(vb);
546 			return;
547 		}
548 		idx = (unsigned char *)"a";
549 	}
550 
551 	agentx_varbind_set_index_string(vb, regressidx_str,
552 	    (const char *)idx);
553 	agentx_varbind_string(vb, (const char *)idx);
554 }
555 
556 void
regress_implstrindex(struct agentx_varbind * vb)557 regress_implstrindex(struct agentx_varbind *vb)
558 {
559 	const unsigned char *idx;
560 	size_t slen;
561 	int implied;
562 	enum agentx_request_type request = agentx_varbind_request(vb);
563 
564 	idx = agentx_varbind_get_index_string(vb, regressidx_str, &slen,
565 	    &implied);
566 
567 	if (!implied)
568 		fatalx("%s: string length should be implied", __func__);
569 
570 	if (slen == 0) {
571 		if (request == AGENTX_REQUEST_TYPE_GET)
572 			fatalx("%s: 0 index should be handled in agentx.c",
573 			    __func__);
574 	}
575 	if (request == AGENTX_REQUEST_TYPE_GET && (slen != 1 ||
576 	    (idx[0] != 'a' && idx[0] != 'b' && idx[0] != 'c'))) {
577 		agentx_varbind_notfound(vb);
578 		return;
579 	}
580 	/* implied doesn't needs a length check before content check */
581 	if (request == AGENTX_REQUEST_TYPE_GETNEXT) {
582 		if (idx[0] == 'a')
583 			idx = (const unsigned char *)"b";
584 		else if (idx[0] == 'b')
585 			idx = (const unsigned char *)"c";
586 		else if (idx[0] >= 'c') {
587 			agentx_varbind_notfound(vb);
588 			return;
589 		}
590 	}
591 	if (idx == NULL || idx[0] < 'a')
592 		idx = (const unsigned char *)"a";
593 
594 	agentx_varbind_set_index_string(vb, regressidx_str,
595 	    (const char *)idx);
596 	agentx_varbind_string(vb, (const char *)idx);
597 }
598 
599 void
regress_strindex2(struct agentx_varbind * vb)600 regress_strindex2(struct agentx_varbind *vb)
601 {
602 	/* Opt is !implied sorted */
603 	const char *opt1[] = {"a", "b", "c"};
604 	const char *opt2[] = {"b", "aa", "bb"};
605 	size_t opt1len, opt2len;
606 	size_t opt1i, opt2i;
607 	const unsigned char *idx1, *idx2;
608 	size_t slen1, slen2;
609 	int implied1, implied2;
610 	enum agentx_request_type request = agentx_varbind_request(vb);
611 	int match;
612 
613 	idx1 = agentx_varbind_get_index_string(vb, regressidx_str, &slen1,
614 	    &implied1);
615 	idx2 = agentx_varbind_get_index_string(vb, regressidx_str2, &slen2,
616 	    &implied2);
617 
618 	/* agentx.c debugging checks */
619 	if (implied1 || implied2)
620 		fatalx("%s: string length should not be implied", __func__);
621 	if (slen1 == 0 || slen2 == 0) {
622 		if (request == AGENTX_REQUEST_TYPE_GET)
623 			fatalx("%s: 0 index should be handled in agentx.c",
624 			    __func__);
625 	}
626 
627 	opt1len = sizeof(opt1) / sizeof(*opt1);
628 	match = 0;
629 	for (opt1i = 0; opt1i < opt1len; opt1i++) {
630 		if (strlen(opt1[opt1i]) < slen1 ||
631 		    (strlen(opt1[opt1i]) == slen1 &&
632 		    memcmp(opt1[opt1i], idx1, slen1) < 0)) {
633 			continue;
634 		}
635 		if (strlen(opt1[opt1i]) == slen1 &&
636 		    memcmp(opt1[opt1i], idx1, slen1) == 0)
637 			match = 1;
638 		break;
639 	}
640 	if (opt1i == opt1len) {
641 		agentx_varbind_notfound(vb);
642 		return;
643 	}
644 	opt2len = sizeof(opt2) / sizeof(*opt2);
645 	for (opt2i = 0; opt2i < opt2len; opt2i++) {
646 		if (!match)
647 			break;
648 		if (strlen(opt2[opt2i]) < slen2 ||
649 		    (strlen(opt2[opt2i]) == slen2 &&
650 		    memcmp(opt2[opt2i], idx2, slen2) < 0)) {
651 			continue;
652 		}
653 		if (strlen(opt2[opt2i]) != slen2 ||
654 		    memcmp(opt2[opt2i], idx2, slen2) > 0)
655 			match = 0;
656 		break;
657 	}
658 	if (opt2i == opt2len)
659 		match = 0;
660 	if (request == AGENTX_REQUEST_TYPE_GET) {
661 		if (!match) {
662 			agentx_varbind_notfound(vb);
663 			return;
664 		}
665 	} else {
666 		if (AGENTX_REQUEST_TYPE_GETNEXT && match)
667 			opt2i++;
668 		if (opt2i >= opt2len) {
669 			if (++opt1i == opt1len) {
670 				agentx_varbind_notfound(vb);
671 				return;
672 			}
673 			opt2i = 0;
674 		}
675 	}
676 
677 	agentx_varbind_set_index_string(vb, regressidx_str, opt1[opt1i]);
678 	agentx_varbind_set_index_string(vb, regressidx_str2, opt2[opt2i]);
679 	agentx_varbind_printf(vb, "%s - %s", opt1[opt1i], opt2[opt2i]);
680 }
681 
682 void
regress_oidimplindex(struct agentx_varbind * vb)683 regress_oidimplindex(struct agentx_varbind *vb)
684 {
685 	struct agentx_object *obj;
686 	const uint32_t *idx;
687 	size_t oidlen;
688 	int implied;
689 	enum agentx_request_type request = agentx_varbind_request(vb);
690 
691 	idx = agentx_varbind_get_index_oid(vb, regressidx_oid, &oidlen,
692 	    &implied);
693 
694 	if (!implied)
695 		fatalx("%s: string length should be implied", __func__);
696 
697 	if (request == AGENTX_REQUEST_TYPE_GET)
698 		obj = agentx_context_object_find(sac, idx, oidlen, 1, 1);
699 	else
700 		obj = agentx_context_object_nfind(sac, idx, oidlen, 1,
701 		    request == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE);
702 
703 	if (obj == NULL) {
704 		agentx_varbind_notfound(vb);
705 		return;
706 	}
707 
708 	agentx_varbind_set_index_object(vb, regressidx_oid, obj);
709 	agentx_varbind_object(vb, obj);
710 }
711 
712 void
regress_ipaddressindex(struct agentx_varbind * vb)713 regress_ipaddressindex(struct agentx_varbind *vb)
714 {
715 	const struct in_addr *addr;
716 	struct in_addr addrlist[4];
717 	enum agentx_request_type request = agentx_varbind_request(vb);
718 	size_t i;
719 	int cmp;
720 
721 	inet_pton(AF_INET, "10.0.0.0", &(addrlist[0]));
722 	inet_pton(AF_INET, "127.0.0.1", &(addrlist[1]));
723 	inet_pton(AF_INET, "172.16.0.0", &(addrlist[2]));
724 	inet_pton(AF_INET, "192.168.0.0", &(addrlist[3]));
725 
726 	addr = agentx_varbind_get_index_ipaddress(vb, regressidx_ipaddress);
727 
728 	for (i = 0; i < 4; i++) {
729 		if ((cmp = memcmp(&(addrlist[i]), addr, sizeof(*addr))) == 0) {
730 			if (request == AGENTX_REQUEST_TYPE_GET ||
731 			    request == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
732 				break;
733 		} else if (cmp > 0) {
734 			if (request == AGENTX_REQUEST_TYPE_GET) {
735 				agentx_varbind_notfound(vb);
736 				return;
737 			}
738 			break;
739 		}
740 	}
741 	if (i == 4) {
742 		agentx_varbind_notfound(vb);
743 		return;
744 	}
745 
746 	agentx_varbind_set_index_ipaddress(vb, regressidx_ipaddress,
747 	    &(addrlist[i]));
748 	agentx_varbind_ipaddress(vb, &(addrlist[i]));
749 }
750 
751 void
regress_intindexstaticvalueint(struct agentx_varbind * vb)752 regress_intindexstaticvalueint(struct agentx_varbind *vb)
753 {
754 	uint32_t idx;
755 
756 	idx = agentx_varbind_get_index_integer(vb, regressidx_value);
757 	agentx_varbind_integer(vb, idx);
758 }
759 
760 void
regress_intindexstaticvaluestring(struct agentx_varbind * vb)761 regress_intindexstaticvaluestring(struct agentx_varbind *vb)
762 {
763 	uint32_t idx;
764 
765 	idx = agentx_varbind_get_index_integer(vb, regressidx_value);
766 	agentx_varbind_printf(vb, "%u", idx);
767 }
768 
769 void
regress_intindexstaticanyint(struct agentx_varbind * vb)770 regress_intindexstaticanyint(struct agentx_varbind *vb)
771 {
772 	uint32_t idx;
773 
774 	idx = agentx_varbind_get_index_integer(vb, regressidx_any);
775 	agentx_varbind_integer(vb, idx);
776 }
777 
778 void
regress_intindexstaticanystring(struct agentx_varbind * vb)779 regress_intindexstaticanystring(struct agentx_varbind *vb)
780 {
781 	uint32_t idx;
782 
783 	idx = agentx_varbind_get_index_integer(vb, regressidx_any);
784 	agentx_varbind_printf(vb, "%u", idx);
785 }
786 
787 void
regress_intindexstaticnewint(struct agentx_varbind * vb)788 regress_intindexstaticnewint(struct agentx_varbind *vb)
789 {
790 	uint32_t idx;
791 
792 	idx = agentx_varbind_get_index_integer(vb, regressidx_new);
793 	agentx_varbind_integer(vb, idx);
794 }
795 
796 void
regress_intindexstaticnewstring(struct agentx_varbind * vb)797 regress_intindexstaticnewstring(struct agentx_varbind *vb)
798 {
799 	uint32_t idx;
800 
801 	idx = agentx_varbind_get_index_integer(vb, regressidx_new);
802 	agentx_varbind_printf(vb, "%u", idx);
803 }
804 
805 void
regress_scalarerror(struct agentx_varbind * vb)806 regress_scalarerror(struct agentx_varbind *vb)
807 {
808 	agentx_varbind_error(vb);
809 }
810