GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/relayd/snmp.c Lines: 0 843 0.0 %
Date: 2017-11-07 Branches: 0 666 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: snmp.c,v 1.29 2017/05/28 10:39:15 benno Exp $	*/
2
3
/*
4
 * Copyright (c) 2008 - 2014 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/types.h>
20
#include <sys/socket.h>
21
#include <sys/queue.h>
22
#include <sys/time.h>
23
#include <sys/un.h>
24
25
#include <netinet/in.h>
26
27
#include <limits.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <stdint.h>
31
#include <errno.h>
32
#include <string.h>
33
#include <unistd.h>
34
#include <event.h>
35
#include <imsg.h>
36
37
#include "relayd.h"
38
#include "snmp.h"
39
40
#define	HOST_MAX_SUBIDX		10
41
#define	TABLE_MAX_SUBIDX	3
42
#define	ROUTER_MAX_SUBIDX	6
43
#define	NETROUTE_MAX_SUBIDX	5
44
#define	RELAY_MAX_SUBIDX	10
45
#define	SESSION_MAX_SUBIDX	12
46
#define	RDR_MAX_SUBIDX		10
47
48
#define	OIDIDX_relaydInfo	9
49
50
#define RELAYD_MIB	"1.3.6.1.4.1.30155.3"
51
#define SNMP_ELEMENT(x...)	do {				\
52
	if (snmp_element(RELAYD_MIB x) == -1)			\
53
		goto done;					\
54
} while (0)
55
56
static struct snmp_oid	hosttrapoid = {
57
	{ 1, 3, 6, 1, 4, 1, 30155, 3, 1, 0 },
58
	10
59
};
60
61
static struct snmp_oid	relaydinfooid = {
62
	{ 1, 3, 6, 1, 4, 1, 30155, 3, 2 },
63
	9
64
};
65
66
static struct agentx_handle	*snmp_agentx = NULL;
67
enum privsep_procid		 snmp_procid;
68
69
void	 snmp_sock(int, short, void *);
70
int	 snmp_element(const char *, enum snmp_type, void *, int64_t,
71
	    struct agentx_pdu *);
72
int	 snmp_string2oid(const char *, struct snmp_oid *);
73
char	*snmp_oid2string(struct snmp_oid *, char *, size_t);
74
void	 snmp_event_add(struct relayd *, int);
75
void	 snmp_agentx_process(struct agentx_handle *, struct agentx_pdu *,
76
	    void *);
77
int	 snmp_register(struct relayd *);
78
int	 snmp_unregister(struct relayd *);
79
80
void	*sstodata(struct sockaddr_storage *);
81
size_t	 sstolen(struct sockaddr_storage *);
82
83
struct host *
84
	 snmp_host_byidx(struct relayd *, u_int *, u_int *, u_int, u_int);
85
struct table *
86
	 snmp_table_byidx(struct relayd *, u_int *, u_int *, u_int, u_int);
87
struct router *
88
	 snmp_router_byidx(struct relayd *, u_int *, u_int *, u_int, u_int);
89
struct relay *
90
	 snmp_relay_byidx(struct relayd *, u_int *, u_int *, u_int, u_int);
91
struct rsession *
92
	 snmp_session_byidx(struct relayd *, u_int *, u_int *, u_int, u_int);
93
struct rdr *
94
	 snmp_rdr_byidx(struct relayd *, u_int *, u_int *, u_int, u_int);
95
struct netroute *
96
	 snmp_netroute_byidx(struct relayd *, u_int *, u_int *, u_int, u_int);
97
98
int	 snmp_redirect(struct relayd *, struct snmp_oid *, struct agentx_pdu *,
99
	    int, uint32_t, uint32_t, u_int);
100
int	 snmp_relay(struct relayd *, struct snmp_oid *, struct agentx_pdu *,
101
	    int, uint32_t, uint32_t, u_int);
102
int	 snmp_router(struct relayd *, struct snmp_oid *, struct agentx_pdu *,
103
	    int, uint32_t, uint32_t, u_int);
104
int	 snmp_netroute(struct relayd *, struct snmp_oid *, struct agentx_pdu *,
105
	    int, uint32_t, uint32_t, u_int);
106
int	 snmp_host(struct relayd *, struct snmp_oid *, struct agentx_pdu *,
107
	    int, uint32_t, uint32_t, u_int);
108
int	 snmp_session(struct relayd *, struct snmp_oid *, struct agentx_pdu *,
109
	    int, uint32_t, uint32_t, u_int);
110
int	 snmp_table(struct relayd *, struct snmp_oid *, struct agentx_pdu *,
111
	    int, uint32_t, uint32_t, u_int);
112
113
void
114
snmp_init(struct relayd *env, enum privsep_procid id)
115
{
116
	if (event_initialized(&env->sc_snmpev))
117
		event_del(&env->sc_snmpev);
118
	if (event_initialized(&env->sc_snmpto))
119
		event_del(&env->sc_snmpto);
120
	if (env->sc_snmp != -1) {
121
		if (snmp_agentx) {
122
			snmp_unregister(env);
123
			snmp_agentx_close(snmp_agentx, AGENTX_CLOSE_OTHER);
124
			snmp_agentx = NULL;
125
		}
126
		close(env->sc_snmp);
127
		env->sc_snmp = -1;
128
	}
129
130
	if ((env->sc_conf.flags & F_SNMP) == 0)
131
		return;
132
133
	snmp_procid = id;
134
135
	proc_compose(env->sc_ps, snmp_procid, IMSG_SNMPSOCK, NULL, 0);
136
}
137
138
void
139
snmp_setsock(struct relayd *env, enum privsep_procid id)
140
{
141
	struct sockaddr_un	 sun;
142
	int			 s = -1;
143
144
	if ((s = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
145
		goto done;
146
147
	bzero(&sun, sizeof(sun));
148
	sun.sun_family = AF_UNIX;
149
	if (strlcpy(sun.sun_path, env->sc_conf.snmp_path,
150
	    sizeof(sun.sun_path)) >= sizeof(sun.sun_path))
151
		fatalx("invalid socket path");
152
153
	if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
154
		close(s);
155
		s = -1;
156
	}
157
 done:
158
	proc_compose_imsg(env->sc_ps, id, -1, IMSG_SNMPSOCK, -1, s, NULL, 0);
159
}
160
161
int
162
snmp_getsock(struct relayd *env, struct imsg *imsg)
163
{
164
	struct timeval		 tv = SNMP_RECONNECT_TIMEOUT;
165
	struct agentx_pdu	*pdu;
166
167
	if (imsg->fd == -1)
168
		goto retry;
169
170
	env->sc_snmp = imsg->fd;
171
172
	log_debug("%s: got new snmp socket %d", __func__, imsg->fd);
173
174
	if ((snmp_agentx = snmp_agentx_alloc(env->sc_snmp)) == NULL)
175
		fatal("%s: agentx alloc", __func__);
176
	if ((pdu = snmp_agentx_open_pdu(snmp_agentx, "relayd", NULL)) == NULL)
177
		fatal("%s: agentx pdu", __func__);
178
	(void)snmp_agentx_send(snmp_agentx, pdu);
179
180
	snmp_event_add(env, EV_WRITE);
181
182
	return (0);
183
 retry:
184
	evtimer_set(&env->sc_snmpto, snmp_sock, env);
185
	evtimer_add(&env->sc_snmpto, &tv);
186
	return (0);
187
}
188
189
void
190
snmp_event_add(struct relayd *env, int wflag)
191
{
192
	event_del(&env->sc_snmpev);
193
	event_set(&env->sc_snmpev, env->sc_snmp, EV_READ|wflag, snmp_sock, env);
194
	event_add(&env->sc_snmpev, NULL);
195
}
196
197
void
198
snmp_sock(int fd, short event, void *arg)
199
{
200
	struct relayd		*env = arg;
201
	struct agentx_pdu	*pdu;
202
	int			 evflags = 0;
203
204
	if (event & EV_TIMEOUT) {
205
		goto reopen;
206
	}
207
	if (event & EV_WRITE) {
208
		if (snmp_agentx_send(snmp_agentx, NULL) == -1) {
209
			if (errno != EAGAIN)
210
				goto close;
211
212
			/* short write */
213
			evflags |= EV_WRITE;
214
		}
215
	}
216
	if (event & EV_READ) {
217
		if ((pdu = snmp_agentx_recv(snmp_agentx)) == NULL) {
218
			if (snmp_agentx->error) {
219
				log_warnx("agentx protocol error '%i'",
220
				    snmp_agentx->error);
221
				goto close;
222
			}
223
			if (errno != EAGAIN) {
224
				log_warn("agentx socket error");
225
				goto close;
226
			}
227
228
			/* short read */
229
			goto out;
230
		}
231
232
		snmp_agentx_process(snmp_agentx, pdu, env);
233
	}
234
out:
235
	snmp_event_add(env, evflags);
236
	return;
237
238
 close:
239
	log_debug("%s: snmp socket closed %d", __func__, env->sc_snmp);
240
	snmp_agentx_free(snmp_agentx);
241
	env->sc_snmp = -1;
242
	snmp_agentx = NULL;
243
 reopen:
244
	proc_compose(env->sc_ps, snmp_procid, IMSG_SNMPSOCK, NULL, 0);
245
	return;
246
}
247
248
void
249
snmp_agentx_process(struct agentx_handle *h, struct agentx_pdu *pdu, void *arg)
250
{
251
	struct agentx_getbulk_repeaters		 repeaters;
252
	struct agentx_search_range		 sr;
253
	struct snmp_oid				 oid;
254
	struct agentx_close_request_data	 close_hdr;
255
	struct relayd				*env = arg;
256
	struct agentx_pdu			*resp;
257
	u_int					 erridx = 0;
258
	int					 getnext = 0, repetitions;
259
	int					 nonrepeaters, maxrepetitions;
260
261
	nonrepeaters = maxrepetitions = -1;
262
263
	switch (pdu->hdr->type) {
264
	case AGENTX_CLOSE:
265
		snmp_agentx_read_raw(pdu, &close_hdr, sizeof(close_hdr));
266
		log_info("snmp: agentx master has closed connection (%i)",
267
		    close_hdr.reason);
268
269
		snmp_agentx_free(snmp_agentx);
270
		env->sc_snmp = -1;
271
		snmp_agentx = NULL;
272
		proc_compose(env->sc_ps, snmp_procid, IMSG_SNMPSOCK, NULL, 0);
273
		break;
274
275
	case AGENTX_GET_BULK:
276
		if (snmp_agentx_read_raw(pdu,
277
		    &repeaters, sizeof(repeaters)) == -1)
278
			break;
279
280
		nonrepeaters = repeaters.nonrepeaters;
281
		maxrepetitions = repeaters.maxrepetitions;
282
283
		/* FALLTHROUGH */
284
	case AGENTX_GET:
285
	case AGENTX_GET_NEXT:
286
		if ((resp = snmp_agentx_response_pdu(0,
287
		    AGENTX_ERR_NONE, 0)) == NULL) {
288
			log_warn("%s unable to allocate response pdu",
289
			    __func__);
290
			break;
291
		}
292
		repetitions = 0;
293
 repeat:
294
		while (pdu->datalen > sizeof(struct agentx_hdr)) {
295
			uint32_t infoendidx, infoentryendidx,
296
			    infoentryidxendidx;
297
298
			erridx++;
299
300
			/* AgentX GETs are the OID followed by the null OID */
301
			if (snmp_agentx_read_searchrange(pdu, &sr) == -1) {
302
				snmp_agentx_pdu_free(resp);
303
				resp = NULL;
304
				break;
305
			}
306
307
			if (sr.end.o_n >= OIDIDX_relaydInfo + 1)
308
				infoendidx = sr.end.o_id[OIDIDX_relaydInfo];
309
			else
310
				infoendidx = UINT32_MAX;
311
			if (sr.end.o_n >= OIDIDX_relaydInfo + 1 + 1)
312
				infoentryendidx =
313
				    sr.end.o_id[OIDIDX_relaydInfo + 1];
314
			else
315
				infoentryendidx = UINT32_MAX;
316
			if (sr.end.o_n >= OIDIDX_relaydInfo + 2 + 1)
317
				infoentryidxendidx =
318
				    sr.end.o_id[OIDIDX_relaydInfo + 2];
319
			else
320
				infoentryidxendidx = UINT32_MAX;
321
322
			bcopy(&sr.start, &oid, sizeof(oid));
323
324
			/*
325
			 * If the requested OID is not part of the registered
326
			 * MIB, return "no such object", per RFC
327
			 */
328
			if (snmp_oid_cmp(&relaydinfooid, &oid) == -1) {
329
				if (snmp_agentx_varbind(resp, &sr.start,
330
				    AGENTX_NO_SUCH_OBJECT, NULL, 0) == -1) {
331
					log_warn("%s: unable to generate"
332
					    " response", __func__);
333
					snmp_agentx_pdu_free(resp);
334
					resp = NULL;
335
				}
336
				goto reply;
337
			}
338
339
			if (oid.o_n != OIDIDX_relaydInfo + 2 + 1) {
340
				/* GET requests require the exact OID */
341
				if (pdu->hdr->type == AGENTX_GET)
342
					goto nosuchinstance;
343
344
				if (oid.o_n == OIDIDX_relaydInfo + 1) {
345
					oid.o_id[OIDIDX_relaydInfo + 1] = 0;
346
					oid.o_n = OIDIDX_relaydInfo + 1 + 1;
347
				}
348
				if (oid.o_n == OIDIDX_relaydInfo + 1 + 1) {
349
					oid.o_id[OIDIDX_relaydInfo + 2] = 0;
350
					oid.o_n = OIDIDX_relaydInfo + 2 + 1;
351
				}
352
				if (oid.o_n > OIDIDX_relaydInfo + 2 + 1)
353
					oid.o_n = OIDIDX_relaydInfo + 2 + 1;
354
			}
355
356
			/*
357
			 * If not including the starting OID, increment
358
			 * here to go to the 'next' OID to allow the lookups
359
			 * to work correctly, as they do 'include' matching
360
			 */
361
			if (pdu->hdr->type == AGENTX_GET_NEXT)
362
				getnext = 1;
363
364
			switch (oid.o_id[OIDIDX_relaydInfo]) {
365
			case 1:
366
				log_warnx("%s: redirects", __func__);
367
				if (infoendidx < 1)
368
					break;
369
				if (snmp_redirect(env, &oid, resp, getnext,
370
				    infoentryendidx, infoentryidxendidx,
371
				    sr.include) == 0)
372
					break;
373
				if (!getnext)
374
					goto nosuchinstance;
375
376
				oid.o_id[OIDIDX_relaydInfo] = 2;
377
				oid.o_id[OIDIDX_relaydInfo + 1] = 0;
378
				oid.o_id[OIDIDX_relaydInfo + 2] = 0;
379
				/* FALLTHROUGH */
380
			case 2:
381
				log_warnx("%s: relays", __func__);
382
				if (infoendidx < 2)
383
					break;
384
				if (snmp_relay(env, &oid, resp, getnext,
385
				    infoentryendidx, infoentryidxendidx,
386
				    sr.include) == 0)
387
					break;
388
				if (!getnext)
389
					goto nosuchinstance;
390
391
				oid.o_id[OIDIDX_relaydInfo] = 3;
392
				oid.o_id[OIDIDX_relaydInfo + 1] = 0;
393
				oid.o_id[OIDIDX_relaydInfo + 2] = 0;
394
				/* FALLTHROUGH */
395
			case 3:
396
				log_warnx("%s: routers", __func__);
397
				if (infoendidx < 3)
398
					break;
399
				if (snmp_router(env, &oid, resp, getnext,
400
				    infoentryendidx, infoentryidxendidx,
401
				    sr.include) == 0)
402
					break;
403
				if (!getnext)
404
					goto nosuchinstance;
405
406
				oid.o_id[OIDIDX_relaydInfo] = 4;
407
				oid.o_id[OIDIDX_relaydInfo + 1] = 0;
408
				oid.o_id[OIDIDX_relaydInfo + 2] = 0;
409
				/* FALLTHROUGH */
410
			case 4:
411
				log_warnx("%s: relaydNetRoutes", __func__);
412
				if (infoendidx < 4)
413
					break;
414
				if (snmp_netroute(env, &oid, resp, getnext,
415
				    infoentryendidx, infoentryidxendidx,
416
				    sr.include) == 0)
417
					break;
418
				if (!getnext)
419
					goto nosuchinstance;
420
421
				oid.o_id[OIDIDX_relaydInfo] = 5;
422
				oid.o_id[OIDIDX_relaydInfo + 1] = 0;
423
				oid.o_id[OIDIDX_relaydInfo + 2] = 0;
424
				/* FALLTHROUGH */
425
			case 5:
426
				log_warnx("%s: hosts", __func__);
427
				if (infoendidx < 5)
428
					break;
429
				if (snmp_host(env, &oid, resp, getnext,
430
				    infoentryendidx, infoentryidxendidx,
431
				    sr.include) == 0)
432
					break;
433
				if (!getnext)
434
					goto nosuchinstance;
435
436
				oid.o_id[OIDIDX_relaydInfo] = 6;
437
				oid.o_id[OIDIDX_relaydInfo + 1] = 0;
438
				oid.o_id[OIDIDX_relaydInfo + 2] = 0;
439
				/* FALLTHROUGH */
440
			case 6:
441
				log_warnx("%s: sessions", __func__);
442
				if (infoendidx < 6)
443
					break;
444
				if (snmp_session(env, &oid, resp, getnext,
445
				    infoentryendidx, infoentryidxendidx,
446
				    sr.include) == 0)
447
					break;
448
				if (!getnext)
449
					goto nosuchinstance;
450
451
				oid.o_id[OIDIDX_relaydInfo] = 7;
452
				oid.o_id[OIDIDX_relaydInfo + 1] = 0;
453
				oid.o_id[OIDIDX_relaydInfo + 2] = 0;
454
				/* FALLTHROUGH */
455
			case 7:
456
				log_warnx("%s: tables", __func__);
457
				if (infoendidx < 7)
458
					break;
459
				if (snmp_table(env, &oid, resp, getnext,
460
				    infoentryendidx, infoentryidxendidx,
461
				    sr.include) == 0)
462
					break;
463
				if (!getnext)
464
					goto nosuchinstance;
465
466
				if (snmp_agentx_varbind(resp, &oid,
467
				    AGENTX_END_OF_MIB_VIEW, NULL, 0) == -1) {
468
					log_warn("%s: unable to generate"
469
					    " response", __func__);
470
					snmp_agentx_pdu_free(resp);
471
					resp = NULL;
472
				}
473
				goto reply;
474
			default:
475
 nosuchinstance:
476
				log_warnx("unknown index %i",
477
				    oid.o_id[OIDIDX_relaydInfo]);
478
				if (snmp_agentx_varbind(resp, &sr.start,
479
				    AGENTX_NO_SUCH_INSTANCE, NULL, 0) == -1) {
480
					log_warn("%s: unable to generate"
481
					    " response", __func__);
482
					snmp_agentx_pdu_free(resp);
483
					resp = NULL;
484
				}
485
				goto reply;
486
			}
487
		}
488
489
		if (pdu->hdr->type == AGENTX_GET_BULK) {
490
			if (nonrepeaters >= 0)
491
				nonrepeaters--;
492
			else if (repetitions < maxrepetitions) {
493
				repetitions++;
494
				goto repeat;
495
			}
496
		}
497
 reply:
498
		if (resp) {
499
			snmp_agentx_send(snmp_agentx, resp);
500
			snmp_event_add(env, EV_WRITE);
501
		}
502
503
		break;
504
505
	case AGENTX_TEST_SET:
506
	case AGENTX_COMMIT_SET:
507
	case AGENTX_UNDO_SET:
508
	case AGENTX_CLEANUP_SET:
509
		log_warnx("unimplemented request type '%s'",
510
		    snmp_agentx_type2name(pdu->hdr->type));
511
		break;
512
513
	case AGENTX_RESPONSE:
514
		switch (pdu->request->hdr->type) {
515
		case AGENTX_NOTIFY:
516
			if (snmp_agentx_response(h, pdu) == -1)
517
				break;
518
		break;
519
520
		case AGENTX_OPEN:
521
			if (snmp_agentx_open_response(h, pdu) == -1)
522
				break;
523
			/* Open AgentX socket; register MIB if not trap-only */
524
			if (!(env->sc_conf.flags & F_SNMP_TRAPONLY))
525
				if (snmp_register(env) == -1) {
526
					log_warn("failed to register MIB");
527
					break;
528
				}
529
			break;
530
531
		case AGENTX_CLOSE:
532
			if (snmp_agentx_response(h, pdu) == -1)
533
				break;
534
			break;
535
536
		case AGENTX_REGISTER:
537
			if (snmp_agentx_response(h, pdu) == -1)
538
				break;
539
			break;
540
541
		case AGENTX_UNREGISTER:
542
			if (snmp_agentx_response(h, pdu) == -1)
543
				break;
544
			break;
545
546
		default:
547
			if (snmp_agentx_response(h, pdu) == -1)
548
				break;
549
			break;
550
		}
551
		break;
552
553
	/* these are nonsensical for subagents to receive */
554
	case AGENTX_OPEN:
555
	case AGENTX_REGISTER:
556
	case AGENTX_UNREGISTER:
557
	case AGENTX_NOTIFY:
558
	case AGENTX_PING:
559
	case AGENTX_INDEX_ALLOCATE:
560
	case AGENTX_INDEX_DEALLOCATE:
561
	case AGENTX_ADD_AGENT_CAPS:
562
	case AGENTX_REMOVE_AGENT_CAPS:
563
		log_warnx("ignoring request type '%s'",
564
		    snmp_agentx_type2name(pdu->hdr->type));
565
		break;
566
567
	default:
568
		log_warnx("unknown request type '%i'", pdu->hdr->type);
569
		if (snmp_agentx_response(h, pdu) == -1)
570
			break;
571
		break;
572
	}
573
574
	snmp_agentx_pdu_free(pdu);
575
	return;
576
}
577
578
int
579
snmp_register(struct relayd *env)
580
{
581
	struct agentx_pdu	*pdu;
582
583
	if ((pdu = snmp_agentx_register_pdu(&relaydinfooid, 3, 0, 0)) == NULL)
584
		return (-1);
585
586
	if (snmp_agentx_send(snmp_agentx, pdu) == -1)
587
		return (-1);
588
589
	snmp_event_add(env, EV_WRITE);
590
	return (0);
591
}
592
593
int
594
snmp_unregister(struct relayd *env)
595
{
596
	struct agentx_pdu	*pdu;
597
598
	if ((pdu = snmp_agentx_unregister_pdu(&relaydinfooid, 0, 0)) == NULL)
599
		return (-1);
600
601
	if (snmp_agentx_send(snmp_agentx, pdu) == -1)
602
		return (-1);
603
604
	snmp_event_add(env, EV_WRITE);
605
	return (0);
606
}
607
608
int
609
snmp_element(const char *oidstr, enum snmp_type type, void *buf, int64_t val,
610
    struct agentx_pdu *pdu)
611
{
612
	u_int32_t		 d;
613
	u_int64_t		 l;
614
	struct snmp_oid		 oid;
615
616
	DPRINTF("%s: oid %s type %d buf %p val %lld", __func__,
617
	    oidstr, type, buf, val);
618
619
	if (snmp_string2oid(oidstr, &oid) == -1)
620
		return (-1);
621
622
	switch (type) {
623
	case SNMP_GAUGE32:
624
	case SNMP_NSAPADDR:
625
	case SNMP_INTEGER32:
626
	case SNMP_UINTEGER32:
627
		d = (u_int32_t)val;
628
		if (snmp_agentx_varbind(pdu, &oid, AGENTX_INTEGER,
629
		    &d, sizeof(d)) == -1)
630
			return (-1);
631
		break;
632
633
	case SNMP_COUNTER32:
634
		d = (u_int32_t)val;
635
		if (snmp_agentx_varbind(pdu, &oid, AGENTX_COUNTER32,
636
		    &d, sizeof(d)) == -1)
637
			return (-1);
638
		break;
639
640
	case SNMP_TIMETICKS:
641
		d = (u_int32_t)val;
642
		if (snmp_agentx_varbind(pdu, &oid, AGENTX_TIME_TICKS,
643
		    &d, sizeof(d)) == -1)
644
			return (-1);
645
		break;
646
647
	case SNMP_COUNTER64:
648
		l = (u_int64_t)val;
649
		if (snmp_agentx_varbind(pdu, &oid, AGENTX_COUNTER64,
650
		    &l, sizeof(l)) == -1)
651
			return (-1);
652
		break;
653
654
	case SNMP_IPADDR:
655
	case SNMP_OPAQUE:
656
		d = (u_int32_t)val;
657
		if (snmp_agentx_varbind(pdu, &oid, AGENTX_OPAQUE,
658
		    buf, strlen(buf)) == -1)
659
			return (-1);
660
		break;
661
662
	case SNMP_OBJECT: {
663
		struct snmp_oid		oid1;
664
665
		if (snmp_string2oid(buf, &oid1) == -1)
666
			return (-1);
667
		if (snmp_agentx_varbind(pdu, &oid, AGENTX_OBJECT_IDENTIFIER,
668
		    &oid1, sizeof(oid1)) == -1)
669
			return (-1);
670
	}
671
672
	case SNMP_BITSTRING:
673
	case SNMP_OCTETSTRING:
674
		if (snmp_agentx_varbind(pdu, &oid, AGENTX_OCTET_STRING,
675
		    buf, strlen(buf)) == -1)
676
			return (-1);
677
		break;
678
679
	case SNMP_NULL:
680
		/* no data beyond the OID itself */
681
		if (snmp_agentx_varbind(pdu, &oid, AGENTX_NULL,
682
		    NULL, 0) == -1)
683
			return (-1);
684
	}
685
686
	return (0);
687
}
688
689
/*
690
 * SNMP traps for relayd
691
 */
692
693
void
694
snmp_hosttrap(struct relayd *env, struct table *table, struct host *host)
695
{
696
	struct agentx_pdu *pdu;
697
698
	if (snmp_agentx == NULL || env->sc_snmp == -1)
699
		return;
700
701
	/*
702
	 * OPENBSD-RELAYD-MIB host status trap
703
	 * XXX The trap format needs some tweaks and other OIDs
704
	 */
705
706
	if ((pdu = snmp_agentx_notify_pdu(&hosttrapoid)) == NULL)
707
		return;
708
709
	SNMP_ELEMENT(".1.0", SNMP_NULL, NULL, 0, pdu);
710
	SNMP_ELEMENT(".1.1.0", SNMP_OCTETSTRING, host->conf.name, 0, pdu);
711
	SNMP_ELEMENT(".1.2.0", SNMP_INTEGER32, NULL, host->up, pdu);
712
	SNMP_ELEMENT(".1.3.0", SNMP_INTEGER32, NULL, host->last_up, pdu);
713
	SNMP_ELEMENT(".1.4.0", SNMP_INTEGER32, NULL, host->up_cnt, pdu);
714
	SNMP_ELEMENT(".1.5.0", SNMP_INTEGER32, NULL, host->check_cnt, pdu);
715
	SNMP_ELEMENT(".1.6.0", SNMP_OCTETSTRING, table->conf.name, 0, pdu);
716
	SNMP_ELEMENT(".1.7.0", SNMP_INTEGER32, NULL, table->up, pdu);
717
	if (!host->conf.retry)
718
		goto done;
719
	SNMP_ELEMENT(".1.8.0", SNMP_INTEGER32, NULL, host->conf.retry, pdu);
720
	SNMP_ELEMENT(".1.9.0", SNMP_INTEGER32, NULL, host->retry_cnt, pdu);
721
722
 done:
723
	snmp_agentx_send(snmp_agentx, pdu);
724
	snmp_event_add(env, EV_WRITE);
725
}
726
727
int
728
snmp_string2oid(const char *oidstr, struct snmp_oid *o)
729
{
730
	char			*sp, *p, str[BUFSIZ];
731
	const char		*errstr;
732
733
	if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
734
		return (-1);
735
	bzero(o, sizeof(*o));
736
737
	for (p = sp = str; p != NULL; sp = p) {
738
		if ((p = strpbrk(p, ".-")) != NULL)
739
			*p++ = '\0';
740
		o->o_id[o->o_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
741
		if (errstr || o->o_n > SNMP_MAX_OID_LEN)
742
			return (-1);
743
	}
744
745
	return (0);
746
}
747
748
void *
749
sstodata(struct sockaddr_storage *ss)
750
{
751
	if (ss->ss_family == AF_INET)
752
		return (&((struct sockaddr_in *)ss)->sin_addr);
753
	if (ss->ss_family == AF_INET6)
754
		return (&((struct sockaddr_in6 *)ss)->sin6_addr);
755
	return (NULL);
756
}
757
758
size_t
759
sstolen(struct sockaddr_storage *ss)
760
{
761
	if (ss->ss_family == AF_INET)
762
		return (((struct sockaddr_in *)ss)->sin_len);
763
	if (ss->ss_family == AF_INET6)
764
		return (((struct sockaddr_in6 *)ss)->sin6_len);
765
	return (0);
766
}
767
768
struct rdr *
769
snmp_rdr_byidx(struct relayd *env, u_int *instanceidx, u_int *objectidx,
770
    u_int getnext, u_int include)
771
{
772
	struct rdr	*rdr;
773
774
	if (*objectidx > RDR_MAX_SUBIDX)
775
		return (NULL);
776
	if (*objectidx == 0) {
777
		if (!getnext)
778
			return (NULL);
779
		*objectidx = 1;
780
	}
781
782
 restart:
783
	TAILQ_FOREACH(rdr, env->sc_rdrs, entry) {
784
		if (rdr->conf.id >= *instanceidx) {
785
			if (getnext) {
786
				/*  Lexographical ordering */
787
788
				/* 1) try the next instance index */
789
				if (rdr->conf.id == *instanceidx && !include)
790
					rdr = TAILQ_NEXT(rdr, entry);
791
				if (rdr) {
792
					*instanceidx = rdr->conf.id;
793
					return (rdr);
794
				}
795
796
				/* 2) try the next object index */
797
				if (*objectidx < RDR_MAX_SUBIDX) {
798
					*objectidx += 1;
799
					*instanceidx = 1;
800
					include = 1;
801
					goto restart;
802
				}
803
804
				/* 3) no further OIDs under this prefix */
805
				return (NULL);
806
			}
807
808
			if (rdr->conf.id == *instanceidx)
809
				return (rdr);
810
811
			return (NULL);
812
		}
813
	}
814
815
	return (NULL);
816
}
817
818
struct relay *
819
snmp_relay_byidx(struct relayd *env, u_int *instanceidx, u_int *objectidx,
820
    u_int getnext, u_int include)
821
{
822
	struct relay	*rly;
823
824
	if (*objectidx > RELAY_MAX_SUBIDX)
825
		return (NULL);
826
	if (*objectidx == 0) {
827
		if (!getnext)
828
			return (NULL);
829
		*objectidx = 1;
830
	}
831
832
 restart:
833
	TAILQ_FOREACH(rly, env->sc_relays, rl_entry) {
834
		if (rly->rl_conf.id >= *instanceidx) {
835
			if (getnext) {
836
				/*  Lexographical ordering */
837
838
				/* 1) try the next instance index */
839
				if (rly->rl_conf.id == *instanceidx && !include)
840
					rly = TAILQ_NEXT(rly, rl_entry);
841
				if (rly) {
842
					*instanceidx = rly->rl_conf.id;
843
					return (rly);
844
				}
845
846
				/* 2) try the next object index */
847
				if (*objectidx < RELAY_MAX_SUBIDX) {
848
					*objectidx += 1;
849
					*instanceidx = 1;
850
					include = 1;
851
					goto restart;
852
				}
853
854
				/* 3) no further OIDs under this prefix */
855
				return (rly);
856
			}
857
858
			if (rly->rl_conf.id == *instanceidx)
859
				return (rly);
860
861
			return (NULL);
862
		}
863
	}
864
865
	return (NULL);
866
}
867
868
struct router *
869
snmp_router_byidx(struct relayd *env, u_int *instanceidx, u_int *objectidx,
870
    u_int getnext, u_int include)
871
{
872
	struct router	*router;
873
874
	if (*objectidx > ROUTER_MAX_SUBIDX)
875
		return (NULL);
876
	if (*objectidx == 0) {
877
		if (!getnext)
878
			return (NULL);
879
		*objectidx = 1;
880
	}
881
882
 restart:
883
	TAILQ_FOREACH(router, env->sc_rts, rt_entry) {
884
		if (router->rt_conf.id >= *instanceidx) {
885
			if (getnext) {
886
				/*  Lexographical ordering */
887
888
				/* 1) try the next instance index */
889
				if ((router->rt_conf.id == *instanceidx) &&
890
				    !include)
891
					router = TAILQ_NEXT(router, rt_entry);
892
				if (router) {
893
					*instanceidx = router->rt_conf.id;
894
					return (router);
895
				}
896
897
				/* 2) try the next object index */
898
				if (*objectidx < ROUTER_MAX_SUBIDX) {
899
					*objectidx += 1;
900
					*instanceidx = 1;
901
					include = 1;
902
					goto restart;
903
				}
904
905
				/* 3) no further OIDs under this prefix */
906
				return (NULL);
907
			}
908
909
			if (router->rt_conf.id == *instanceidx)
910
				return (router);
911
912
			return (NULL);
913
		}
914
	}
915
916
	return (NULL);
917
}
918
919
struct netroute *
920
snmp_netroute_byidx(struct relayd *env, u_int *instanceidx, u_int *objectidx,
921
    u_int getnext, u_int include)
922
{
923
	struct netroute		*nr;
924
925
	if (*objectidx > NETROUTE_MAX_SUBIDX)
926
		return (NULL);
927
	if (*objectidx == 0) {
928
		if (!getnext)
929
			return (NULL);
930
		*objectidx = 1;
931
	}
932
933
 restart:
934
	TAILQ_FOREACH(nr, env->sc_routes, nr_route) {
935
		if (nr->nr_conf.id >= *instanceidx) {
936
			if (getnext) {
937
				/*  Lexographical ordering */
938
939
				/* 1) try the next instance index */
940
				if (nr->nr_conf.id == *instanceidx && !include)
941
					nr = TAILQ_NEXT(nr, nr_route);
942
				if (nr) {
943
					*instanceidx = nr->nr_conf.id;
944
					return (nr);
945
				}
946
947
				/* 2) try the next object index */
948
				if (*objectidx < NETROUTE_MAX_SUBIDX) {
949
					*objectidx += 1;
950
					*instanceidx = 1;
951
					include = 1;
952
					goto restart;
953
				}
954
955
				/* 3) no further OIDs under this prefix */
956
				return (NULL);
957
			}
958
959
			if (nr->nr_conf.id == *instanceidx)
960
				return (nr);
961
962
			return (NULL);
963
		}
964
	}
965
966
	return (NULL);
967
}
968
969
struct host *
970
snmp_host_byidx(struct relayd *env, u_int *instanceidx, u_int *objectidx,
971
    u_int getnext, u_int include)
972
{
973
	struct host	*host;
974
975
	if (*objectidx > HOST_MAX_SUBIDX)
976
		return (NULL);
977
	if (*objectidx == 0) {
978
		if (!getnext)
979
			return (NULL);
980
		*objectidx = 1;
981
	}
982
983
 restart:
984
	TAILQ_FOREACH(host, &env->sc_hosts, globalentry) {
985
		if (host->conf.id >= *instanceidx) {
986
			if (getnext) {
987
				/*  Lexographical ordering */
988
989
				/* 1) try the next instance index */
990
				if (host->conf.id == *instanceidx && !include)
991
					host = TAILQ_NEXT(host, globalentry);
992
				if (host) {
993
					*instanceidx = host->conf.id;
994
					return (host);
995
				}
996
997
				/* 2) try the next object index */
998
				if (*objectidx < HOST_MAX_SUBIDX) {
999
					*objectidx += 1;
1000
					*instanceidx = 1;
1001
					include = 1;
1002
					goto restart;
1003
				}
1004
1005
				/* 3) no further OIDs under this prefix */
1006
				return (NULL);
1007
			}
1008
1009
			if (host->conf.id == *instanceidx)
1010
				return (host);
1011
1012
			return (NULL);
1013
		}
1014
	}
1015
1016
	return (NULL);
1017
}
1018
1019
struct rsession *
1020
snmp_session_byidx(struct relayd *env, u_int *instanceidx, u_int *objectidx,
1021
    u_int getnext, u_int include)
1022
{
1023
	struct rsession		*session;
1024
1025
	if (*objectidx > SESSION_MAX_SUBIDX)
1026
		return (NULL);
1027
	if (*objectidx == 0) {
1028
		if (!getnext)
1029
			return (NULL);
1030
		*objectidx = 1;
1031
	}
1032
1033
 restart:
1034
	TAILQ_FOREACH(session, &env->sc_sessions, se_entry) {
1035
		if (session->se_id >= *instanceidx) {
1036
			if (getnext) {
1037
				/*  Lexographical ordering */
1038
1039
				/* 1) try the next instance index */
1040
				if (session->se_id == *instanceidx && !include)
1041
					session = TAILQ_NEXT(session, se_entry);
1042
				if (session) {
1043
					*instanceidx = session->se_id;
1044
					return (session);
1045
				}
1046
1047
				/* 2) try the next object index */
1048
				if (*objectidx < SESSION_MAX_SUBIDX) {
1049
					*objectidx += 1;
1050
					*instanceidx = 1;
1051
					include = 1;
1052
					goto restart;
1053
				}
1054
1055
				/* 3) no further OIDs under this prefix */
1056
				return (NULL);
1057
			}
1058
1059
			if (session->se_id == *instanceidx)
1060
				return (session);
1061
1062
			return (NULL);
1063
		}
1064
	}
1065
1066
	return (NULL);
1067
}
1068
1069
struct table *
1070
snmp_table_byidx(struct relayd *env, u_int *instanceidx, u_int *objectidx,
1071
    u_int getnext, u_int include)
1072
{
1073
	struct table		*table;
1074
1075
	if (*objectidx > TABLE_MAX_SUBIDX)
1076
		return (NULL);
1077
	if (*objectidx == 0) {
1078
		if (!getnext)
1079
			return (NULL);
1080
		*objectidx = 1;
1081
	}
1082
1083
 restart:
1084
	TAILQ_FOREACH(table, env->sc_tables, entry) {
1085
		if (table->conf.id >= *instanceidx) {
1086
			if (getnext) {
1087
				/*  Lexographical ordering */
1088
1089
				/* 1) try the next instance index */
1090
				if (table->conf.id == *instanceidx && !include)
1091
					table = TAILQ_NEXT(table, entry);
1092
				if (table) {
1093
					*instanceidx = table->conf.id;
1094
					return (table);
1095
				}
1096
1097
				/* 2) try the next object index */
1098
				if (*objectidx < TABLE_MAX_SUBIDX) {
1099
					*objectidx += 1;
1100
					*instanceidx = 1;
1101
					include = 1;
1102
					goto restart;
1103
				}
1104
1105
				/* 3) no further OIDs under this prefix */
1106
				return (NULL);
1107
			}
1108
1109
			if (table->conf.id == *instanceidx)
1110
				return (table);
1111
1112
			return (NULL);
1113
		}
1114
	}
1115
1116
	return (NULL);
1117
}
1118
1119
int
1120
snmp_redirect(struct relayd *env, struct snmp_oid *oid,
1121
    struct agentx_pdu *resp, int getnext, uint32_t einstanceidx,
1122
    uint32_t eobjectidx, u_int include)
1123
{
1124
	struct rdr	*rdr;
1125
	u_int		 instanceidx, objectidx;
1126
	u_int32_t	 status;
1127
1128
	instanceidx = oid->o_id[OIDIDX_relaydInfo + 2];
1129
	objectidx = oid->o_id[OIDIDX_relaydInfo + 1];
1130
	rdr = snmp_rdr_byidx(env, &instanceidx, &objectidx, getnext, include);
1131
	if (rdr == NULL)
1132
		return (-1);
1133
1134
	if (instanceidx >= einstanceidx || objectidx >= eobjectidx)
1135
		return (0);
1136
1137
	oid->o_id[OIDIDX_relaydInfo + 1] = objectidx;
1138
	oid->o_id[OIDIDX_relaydInfo + 2] = instanceidx;
1139
1140
	switch (objectidx) {
1141
	case 1:		/* index */
1142
		if (snmp_agentx_varbind(resp, oid,
1143
		    AGENTX_INTEGER, &rdr->conf.id,
1144
		    sizeof(rdr->conf.id)) == -1)
1145
			return (-1);
1146
		break;
1147
	case 2:		/* status */
1148
		if (rdr->conf.flags & F_DISABLE)
1149
			status = 1;
1150
		else if (rdr->conf.flags & F_DOWN)
1151
			status = 2;
1152
		else if (rdr->conf.flags & F_BACKUP)
1153
			status = 3;
1154
		else
1155
			status = 0;
1156
		if (snmp_agentx_varbind(resp, oid,
1157
		    AGENTX_INTEGER, &status,
1158
		    sizeof(status)) == -1)
1159
			return (-1);
1160
		break;
1161
	case 3:		/* name */
1162
		if (snmp_agentx_varbind(resp, oid,
1163
		    AGENTX_OCTET_STRING, rdr->conf.name,
1164
		    strlen(rdr->conf.name)) == -1)
1165
			return (-1);
1166
		break;
1167
	case 4:		/* count */
1168
		if (snmp_agentx_varbind(resp, oid,
1169
		    AGENTX_COUNTER64, &rdr->stats.cnt,
1170
		    sizeof(rdr->stats.cnt)) == -1)
1171
			return (-1);
1172
		break;
1173
	case 5:		/* average */
1174
		if (snmp_agentx_varbind(resp, oid,
1175
		    AGENTX_INTEGER, &rdr->stats.avg,
1176
		    sizeof(rdr->stats.avg)) == -1)
1177
			return (-1);
1178
		break;
1179
	case 6:		/* last */
1180
		if (snmp_agentx_varbind(resp, oid,
1181
		    AGENTX_INTEGER, &rdr->stats.last,
1182
		    sizeof(rdr->stats.last)) == -1)
1183
			return (-1);
1184
		break;
1185
	case 7:		/* average hour */
1186
		if (snmp_agentx_varbind(resp, oid,
1187
		    AGENTX_INTEGER, &rdr->stats.avg_hour,
1188
		    sizeof(rdr->stats.avg_hour)) == -1)
1189
			return (-1);
1190
		break;
1191
	case 8:		/* last hour */
1192
		if (snmp_agentx_varbind(resp, oid,
1193
		    AGENTX_INTEGER, &rdr->stats.last_hour,
1194
		    sizeof(rdr->stats.last_hour)) == -1)
1195
			return (-1);
1196
		break;
1197
	case 9:		/* average day */
1198
		if (snmp_agentx_varbind(resp, oid,
1199
		    AGENTX_INTEGER, &rdr->stats.avg_day,
1200
		    sizeof(rdr->stats.avg_day)) == -1)
1201
			return (-1);
1202
		break;
1203
	case 10:	/* last day */
1204
		if (snmp_agentx_varbind(resp, oid,
1205
		    AGENTX_INTEGER, &rdr->stats.last_day,
1206
		    sizeof(rdr->stats.last_day)) == -1)
1207
			return (-1);
1208
		break;
1209
	default:
1210
		fatalx("unhandled host element id");
1211
	}
1212
1213
	return (0);
1214
}
1215
1216
int
1217
snmp_relay(struct relayd *env, struct snmp_oid *oid, struct agentx_pdu *resp,
1218
    int getnext, uint32_t einstanceidx, uint32_t eobjectidx, u_int include)
1219
{
1220
	struct relay	*rly;
1221
	u_int		 instanceidx, objectidx;
1222
	u_int32_t	 status, value = 0;
1223
	u_int64_t	 value64 = 0;
1224
	int		 i, nrelay = env->sc_conf.prefork_relay;
1225
1226
	instanceidx = oid->o_id[OIDIDX_relaydInfo + 2];
1227
	objectidx = oid->o_id[OIDIDX_relaydInfo + 1];
1228
	rly = snmp_relay_byidx(env, &instanceidx, &objectidx, getnext,
1229
	    include);
1230
	if (rly == NULL)
1231
		return (-1);
1232
1233
	if (instanceidx >= einstanceidx || objectidx >= eobjectidx)
1234
		return (0);
1235
1236
	oid->o_id[OIDIDX_relaydInfo + 1] = objectidx;
1237
	oid->o_id[OIDIDX_relaydInfo + 2] = instanceidx;
1238
1239
	switch (objectidx) {
1240
	case 1:		/* index */
1241
		if (snmp_agentx_varbind(resp, oid,
1242
		    AGENTX_INTEGER, &rly->rl_conf.id,
1243
		    sizeof(rly->rl_conf.id)) == -1)
1244
			return (-1);
1245
		break;
1246
	case 2:		/* status */
1247
		if (rly->rl_up == HOST_UP)
1248
			status = 0;		/* active */
1249
		else
1250
			status = 1;		/* disabled */
1251
		if (snmp_agentx_varbind(resp, oid,
1252
		    AGENTX_INTEGER, &status,
1253
		    sizeof(status)) == -1)
1254
			return (-1);
1255
		break;
1256
	case 3:		/* name */
1257
		if (snmp_agentx_varbind(resp, oid,
1258
		    AGENTX_OCTET_STRING, &rly->rl_conf.name,
1259
		    strlen(rly->rl_conf.name)) == -1)
1260
			return (-1);
1261
		break;
1262
	case 4:		/* count */
1263
		for (i = 0; i < nrelay; i++)
1264
			value64 += rly->rl_stats[i].cnt;
1265
		if (snmp_agentx_varbind(resp, oid,
1266
		    AGENTX_COUNTER64, &value64,
1267
		    sizeof(value64)) == -1)
1268
			return (-1);
1269
		break;
1270
	case 5:		/* average */
1271
		for (i = 0; i < nrelay; i++)
1272
			value += rly->rl_stats[i].avg;
1273
		if (snmp_agentx_varbind(resp, oid,
1274
		    AGENTX_INTEGER, &value,
1275
		    sizeof(value)) == -1)
1276
			return (-1);
1277
		break;
1278
	case 6:		/* last */
1279
		for (i = 0; i < nrelay; i++)
1280
			value += rly->rl_stats[i].last;
1281
		if (snmp_agentx_varbind(resp, oid,
1282
		    AGENTX_INTEGER, &value,
1283
		    sizeof(value)) == -1)
1284
			return (-1);
1285
		break;
1286
	case 7:		/* average hour */
1287
		for (i = 0; i < nrelay; i++)
1288
			value += rly->rl_stats[i].avg_hour;
1289
		if (snmp_agentx_varbind(resp, oid,
1290
		    AGENTX_INTEGER, &value,
1291
		    sizeof(value)) == -1)
1292
			return (-1);
1293
		break;
1294
	case 8:		/* last hour */
1295
		for (i = 0; i < nrelay; i++)
1296
			value += rly->rl_stats[i].last_hour;
1297
		if (snmp_agentx_varbind(resp, oid,
1298
		    AGENTX_INTEGER, &value,
1299
		    sizeof(value)) == -1)
1300
			return (-1);
1301
		break;
1302
	case 9:		/* average day */
1303
		for (i = 0; i < nrelay; i++)
1304
			value += rly->rl_stats[i].avg_day;
1305
		if (snmp_agentx_varbind(resp, oid,
1306
		    AGENTX_INTEGER, &value,
1307
		    sizeof(value)) == -1)
1308
			return (-1);
1309
		break;
1310
	case 10:	/* last day */
1311
		for (i = 0; i < nrelay; i++)
1312
			value += rly->rl_stats[i].last_day;
1313
		if (snmp_agentx_varbind(resp, oid,
1314
		    AGENTX_INTEGER, &value,
1315
		    sizeof(value)) == -1)
1316
			return (-1);
1317
		break;
1318
	default:
1319
		fatalx("unhandled host element id");
1320
	}
1321
1322
	return (0);
1323
}
1324
1325
int
1326
snmp_router(struct relayd *env, struct snmp_oid *oid, struct agentx_pdu *resp,
1327
    int getnext, uint32_t einstanceidx, uint32_t eobjectidx, u_int include)
1328
{
1329
	struct router	*router;
1330
	u_int		 instanceidx, objectidx;
1331
	u_int32_t	 status;
1332
1333
	instanceidx = oid->o_id[OIDIDX_relaydInfo + 2];
1334
	objectidx = oid->o_id[OIDIDX_relaydInfo + 1];
1335
	router = snmp_router_byidx(env, &instanceidx, &objectidx, getnext,
1336
	    include);
1337
	if (router == NULL)
1338
		return (-1);
1339
1340
	if (instanceidx >= einstanceidx || objectidx >= eobjectidx)
1341
		return (0);
1342
1343
	oid->o_id[OIDIDX_relaydInfo + 1] = objectidx;
1344
	oid->o_id[OIDIDX_relaydInfo + 2] = instanceidx;
1345
1346
	switch (objectidx) {
1347
	case 1:		/* index */
1348
		if (snmp_agentx_varbind(resp, oid,
1349
		    AGENTX_INTEGER, &router->rt_conf.id,
1350
		    sizeof(router->rt_conf.id)) == -1)
1351
			return (-1);
1352
		break;
1353
	case 2:		/* table index */
1354
		if (snmp_agentx_varbind(resp, oid,
1355
		    AGENTX_INTEGER, &router->rt_conf.gwtable,
1356
		    sizeof(router->rt_conf.gwtable)) == -1)
1357
			return (-1);
1358
		break;
1359
	case 3:		/* status */
1360
		if (router->rt_conf.flags & F_DISABLE)
1361
			status = 1;		/* disabled */
1362
		else
1363
			status = 0;		/* active */
1364
		if (snmp_agentx_varbind(resp, oid,
1365
		    AGENTX_INTEGER, &status,
1366
		    sizeof(status)) == -1)
1367
			return (-1);
1368
		break;
1369
	case 4:		/* name */
1370
		if (snmp_agentx_varbind(resp, oid,
1371
		    AGENTX_OCTET_STRING, router->rt_conf.name,
1372
		    strlen(router->rt_conf.name)) == -1)
1373
			return (-1);
1374
		break;
1375
	case 5:		/* pf label */
1376
		if (snmp_agentx_varbind(resp, oid,
1377
		    AGENTX_OCTET_STRING, router->rt_conf.label,
1378
		    strlen(router->rt_conf.label)) == -1)
1379
			return (-1);
1380
		break;
1381
	case 6:		/* rtable */
1382
		if (snmp_agentx_varbind(resp, oid,
1383
		    AGENTX_INTEGER, &router->rt_conf.rtable,
1384
		    sizeof(router->rt_conf.rtable)) == -1)
1385
			return (-1);
1386
		break;
1387
	default:
1388
		fatalx("unhandled host element id");
1389
	}
1390
1391
	return (0);
1392
}
1393
1394
int
1395
snmp_netroute(struct relayd *env, struct snmp_oid *oid,
1396
    struct agentx_pdu *resp, int getnext, uint32_t einstanceidx,
1397
    uint32_t eobjectidx, u_int include)
1398
{
1399
	struct netroute			*nr;
1400
	u_int32_t			 addrtype;
1401
	u_int				 instanceidx, objectidx;
1402
1403
	instanceidx = oid->o_id[OIDIDX_relaydInfo + 2];
1404
	objectidx = oid->o_id[OIDIDX_relaydInfo + 1];
1405
	nr = snmp_netroute_byidx(env, &instanceidx, &objectidx, getnext,
1406
	    include);
1407
	if (nr == NULL)
1408
		return (-1);
1409
1410
	if (instanceidx >= einstanceidx || objectidx >= eobjectidx)
1411
		return (0);
1412
1413
	oid->o_id[OIDIDX_relaydInfo + 1] = objectidx;
1414
	oid->o_id[OIDIDX_relaydInfo + 2] = instanceidx;
1415
1416
	switch (objectidx) {
1417
	case 1:		/* index */
1418
		if (snmp_agentx_varbind(resp, oid,
1419
		    AGENTX_INTEGER, &nr->nr_conf.id,
1420
		    sizeof(nr->nr_conf.id)) == -1)
1421
			return (-1);
1422
		break;
1423
	case 2:		/* address */
1424
		if (snmp_agentx_varbind(resp, oid,
1425
		    AGENTX_OCTET_STRING, sstodata(&nr->nr_conf.ss),
1426
		    sstolen(&nr->nr_conf.ss)) == -1)
1427
			return (-1);
1428
		break;
1429
	case 3:		/* address type */
1430
		if (nr->nr_conf.ss.ss_family == AF_INET)
1431
			addrtype = 1;
1432
		else if (nr->nr_conf.ss.ss_family == AF_INET6)
1433
			addrtype = 2;
1434
		if (snmp_agentx_varbind(resp, oid,
1435
		    AGENTX_INTEGER, &addrtype,
1436
		    sizeof(addrtype)) == -1)
1437
			return (-1);
1438
		break;
1439
	case 4:		/* prefix length */
1440
		if (snmp_agentx_varbind(resp, oid,
1441
		    AGENTX_INTEGER, &nr->nr_conf.prefixlen,
1442
		    sizeof(nr->nr_conf.prefixlen)) == -1)
1443
			return (-1);
1444
		break;
1445
	case 5:		/* router index */
1446
		if (snmp_agentx_varbind(resp, oid,
1447
		    AGENTX_INTEGER, &nr->nr_conf.routerid,
1448
		    sizeof(nr->nr_conf.routerid)) == -1)
1449
			return (-1);
1450
		break;
1451
	default:
1452
		fatalx("unhandled host element id");
1453
	}
1454
1455
	return (0);
1456
}
1457
1458
int
1459
snmp_host(struct relayd *env, struct snmp_oid *oid, struct agentx_pdu *resp,
1460
    int getnext, uint32_t einstanceidx, uint32_t eobjectidx, u_int include)
1461
{
1462
	struct host			*host;
1463
	u_int32_t			 addrtype, count, error, status;
1464
	u_int				 instanceidx, objectidx;
1465
1466
	instanceidx = oid->o_id[OIDIDX_relaydInfo + 2];
1467
	objectidx = oid->o_id[OIDIDX_relaydInfo + 1];
1468
	host = snmp_host_byidx(env, &instanceidx, &objectidx, getnext,
1469
	    include);
1470
	if (host == NULL)
1471
		return (-1);
1472
1473
	if (instanceidx >= einstanceidx || objectidx >= eobjectidx)
1474
		return (0);
1475
1476
	oid->o_id[OIDIDX_relaydInfo + 1] = objectidx;
1477
	oid->o_id[OIDIDX_relaydInfo + 2] = instanceidx;
1478
1479
	switch (objectidx) {
1480
	case 1:		/* index */
1481
		if (snmp_agentx_varbind(resp, oid,
1482
		    AGENTX_INTEGER, &host->conf.id,
1483
		    sizeof(host->conf.id)) == -1)
1484
			return (-1);
1485
		break;
1486
	case 2:		/* parent index */
1487
		if (snmp_agentx_varbind(resp, oid,
1488
		    AGENTX_INTEGER, &host->conf.parentid,
1489
		    sizeof(host->conf.parentid)) == -1)
1490
			return (-1);
1491
		break;
1492
	case 3:		/* table index */
1493
		if (snmp_agentx_varbind(resp, oid,
1494
		    AGENTX_INTEGER, &host->conf.tableid,
1495
		    sizeof(host->conf.tableid)) == -1)
1496
			return (-1);
1497
		break;
1498
	case 4:		/* name */
1499
		if (snmp_agentx_varbind(resp, oid,
1500
		    AGENTX_OCTET_STRING, host->conf.name,
1501
		    strlen(host->conf.name)) == -1)
1502
			return (-1);
1503
		break;
1504
	case 5:		/* address */
1505
		if (snmp_agentx_varbind(resp, oid,
1506
		    AGENTX_OCTET_STRING, sstodata(&host->conf.ss),
1507
		    sstolen(&host->conf.ss)) == -1)
1508
			return (-1);
1509
		break;
1510
	case 6:		/* address type */
1511
		if (host->conf.ss.ss_family == AF_INET)
1512
			addrtype = 1;
1513
		else if (host->conf.ss.ss_family == AF_INET6)
1514
			addrtype = 2;
1515
		if (snmp_agentx_varbind(resp, oid,
1516
		    AGENTX_INTEGER, &addrtype,
1517
		    sizeof(addrtype)) == -1)
1518
			return (-1);
1519
		break;
1520
	case 7:		/* status */
1521
		if (host->flags & F_DISABLE)
1522
			status = 1;
1523
		else if (host->up == HOST_UP)
1524
			status = 0;
1525
		else if (host->up == HOST_DOWN)
1526
			status = 2;
1527
		else
1528
			status = 3;
1529
		if (snmp_agentx_varbind(resp, oid,
1530
		    AGENTX_INTEGER, &status,
1531
		    sizeof(status)) == -1)
1532
			return (-1);
1533
		break;
1534
	case 8:		/* check count */
1535
		count = host->check_cnt;
1536
		if (snmp_agentx_varbind(resp, oid,
1537
		    AGENTX_INTEGER, &count,
1538
		    sizeof(count)) == -1)
1539
			return (-1);
1540
		break;
1541
	case 9:		/* up count */
1542
		count = host->up_cnt;
1543
		if (snmp_agentx_varbind(resp, oid,
1544
		    AGENTX_INTEGER, &count,
1545
		    sizeof(count)) == -1)
1546
			return (-1);
1547
		break;
1548
	case 10:	/* errno */
1549
		error = host->he;
1550
		if (snmp_agentx_varbind(resp, oid,
1551
		    AGENTX_INTEGER, &error,
1552
		    sizeof(errno)) == -1)
1553
			return (-1);
1554
		break;
1555
	default:
1556
		fatalx("unhandled host element id");
1557
	}
1558
1559
	return (0);
1560
}
1561
1562
int
1563
snmp_session(struct relayd *env, struct snmp_oid *oid, struct agentx_pdu *resp,
1564
    int getnext, uint32_t einstanceidx, uint32_t eobjectidx, u_int include)
1565
{
1566
	struct timeval		 tv, now;
1567
	time_t			 ticks;
1568
	struct rsession		*session;
1569
	u_int			 instanceidx, objectidx;
1570
	u_int32_t		 status, pid, port, addrtype;
1571
1572
	instanceidx = oid->o_id[OIDIDX_relaydInfo + 2];
1573
	objectidx = oid->o_id[OIDIDX_relaydInfo + 1];
1574
	session = snmp_session_byidx(env, &instanceidx, &objectidx, getnext,
1575
	    include);
1576
	if (session == NULL)
1577
		return (-1);
1578
1579
	if (instanceidx >= einstanceidx || objectidx >= eobjectidx)
1580
		return (0);
1581
1582
	oid->o_id[OIDIDX_relaydInfo + 1] = objectidx;
1583
	oid->o_id[OIDIDX_relaydInfo + 2] = instanceidx;
1584
1585
	switch (objectidx) {
1586
	case 1:		/* index */
1587
		if (snmp_agentx_varbind(resp, oid,
1588
		    AGENTX_INTEGER, &session->se_id,
1589
		    sizeof(session->se_id)) == -1)
1590
			return (-1);
1591
		break;
1592
	case 2:		/* relay index */
1593
		if (snmp_agentx_varbind(resp, oid,
1594
		    AGENTX_INTEGER, &session->se_relayid,
1595
		    sizeof(session->se_relayid)) == -1)
1596
			return (-1);
1597
		break;
1598
	case 3:		/* in address */
1599
		if (snmp_agentx_varbind(resp, oid,
1600
		    AGENTX_OCTET_STRING, sstodata(&session->se_in.ss),
1601
		    sstolen(&session->se_in.ss)) == -1)
1602
			return (-1);
1603
		break;
1604
	case 4:		/* in address type */
1605
		if (session->se_in.ss.ss_family == AF_INET)
1606
			addrtype = 1;
1607
		else if (session->se_in.ss.ss_family == AF_INET6)
1608
			addrtype = 2;
1609
		if (snmp_agentx_varbind(resp, oid,
1610
		    AGENTX_INTEGER, &addrtype,
1611
		    sizeof(addrtype)) == -1)
1612
			return (-1);
1613
		break;
1614
	case 5:		/* out address */
1615
		if (snmp_agentx_varbind(resp, oid,
1616
		    AGENTX_OCTET_STRING, sstodata(&session->se_out.ss),
1617
		    sstolen(&session->se_out.ss)) == -1)
1618
			return (-1);
1619
		break;
1620
	case 6:		/* out address type */
1621
		if (session->se_out.ss.ss_family == AF_INET)
1622
			addrtype = 1;
1623
		else if (session->se_out.ss.ss_family == AF_INET6)
1624
			addrtype = 2;
1625
		if (snmp_agentx_varbind(resp, oid,
1626
		    AGENTX_INTEGER, &addrtype,
1627
		    sizeof(addrtype)) == -1)
1628
			return (-1);
1629
		break;
1630
	case 7:		/* port out */
1631
		port = session->se_out.port;
1632
		if (snmp_agentx_varbind(resp, oid,
1633
		    AGENTX_INTEGER, &port,
1634
		    sizeof(port)) == -1)
1635
			return (-1);
1636
		break;
1637
	case 8:		/* port in */
1638
		port = session->se_in.port;
1639
		if (snmp_agentx_varbind(resp, oid,
1640
		    AGENTX_INTEGER, &port,
1641
		    sizeof(port)) == -1)
1642
			return (-1);
1643
		break;
1644
	case 9:		/* age */
1645
		getmonotime(&now);
1646
		timerclear(&tv);
1647
		timersub(&now, &session->se_tv_start, &tv);
1648
		ticks = tv.tv_sec * 100 + tv.tv_usec / 10000;
1649
		if (snmp_agentx_varbind(resp, oid,
1650
		    AGENTX_INTEGER, &ticks,
1651
		    sizeof(ticks)) == -1)
1652
			return (-1);
1653
		break;
1654
	case 10:	/* idle time */
1655
		getmonotime(&now);
1656
		timerclear(&tv);
1657
		timersub(&now, &session->se_tv_last, &tv);
1658
		ticks = tv.tv_sec * 100 + tv.tv_usec / 10000;
1659
		if (snmp_agentx_varbind(resp, oid,
1660
		    AGENTX_INTEGER, &ticks,
1661
		    sizeof(ticks)) == -1)
1662
			return (-1);
1663
		break;
1664
	case 11:	/* status */
1665
		if (session->se_done)
1666
			status = 1;
1667
		else
1668
			status = 0;
1669
		if (snmp_agentx_varbind(resp, oid,
1670
		    AGENTX_INTEGER, &status,
1671
		    sizeof(status)) == -1)
1672
			return (-1);
1673
		break;
1674
	case 12:	/* session pid */
1675
		pid = (u_int32_t)session->se_pid;
1676
		if (snmp_agentx_varbind(resp, oid,
1677
		    AGENTX_INTEGER, &pid,
1678
		    sizeof(pid)) == -1)
1679
			return (-1);
1680
		break;
1681
	default:
1682
		fatalx("unhandled table element id");
1683
	}
1684
1685
	return (0);
1686
}
1687
1688
int
1689
snmp_table(struct relayd *env, struct snmp_oid *oid, struct agentx_pdu *resp,
1690
    int getnext, uint32_t einstanceidx, uint32_t eobjectidx, u_int include)
1691
{
1692
	struct table		*table;
1693
	u_int			 instanceidx, objectidx;
1694
	u_int32_t		 status;
1695
1696
	instanceidx = oid->o_id[OIDIDX_relaydInfo + 2];
1697
	objectidx = oid->o_id[OIDIDX_relaydInfo + 1];
1698
	table = snmp_table_byidx(env, &instanceidx, &objectidx, getnext,
1699
	    include);
1700
	if (table == NULL)
1701
		return (-1);
1702
1703
	if (instanceidx >= einstanceidx || objectidx >= eobjectidx)
1704
		return (0);
1705
1706
	oid->o_id[OIDIDX_relaydInfo + 1] = objectidx;
1707
	oid->o_id[OIDIDX_relaydInfo + 2] = instanceidx;
1708
1709
	switch (objectidx) {
1710
	case 1:		/* index */
1711
		if (snmp_agentx_varbind(resp, oid,
1712
		    AGENTX_INTEGER, &table->conf.id,
1713
		    sizeof(table->conf.id)) == -1)
1714
			return (-1);
1715
		break;
1716
	case 2:		/* name */
1717
		if (snmp_agentx_varbind(resp, oid,
1718
		    AGENTX_OCTET_STRING, &table->conf.name,
1719
		    strlen(table->conf.name)) == -1)
1720
			return (-1);
1721
		break;
1722
	case 3:		/* status */
1723
		if (TAILQ_EMPTY(&table->hosts))
1724
			status = 1;		/* empty */
1725
		else if (table->conf.flags & F_DISABLE)
1726
			status = 2;		/* disabled */
1727
		else
1728
			status = 0;		/* active */
1729
		if (snmp_agentx_varbind(resp, oid,
1730
		    AGENTX_INTEGER, &status,
1731
		    sizeof(status)) == -1)
1732
			return (-1);
1733
		break;
1734
	default:
1735
		fatalx("unhandled table element id");
1736
	}
1737
1738
	return (0);
1739
}