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 ®ressidx_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 ®ressidx_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 ®ressidx_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 ®ressidx_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 ®ressidx_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 ®ressidx_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 ®ressidx_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 ®ressidx_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 ®ressidx_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 ®ressidx_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 ®ressidx_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