1/*	$OpenBSD: application_blocklist.c,v 1.2 2023/12/21 12:43:31 martijn Exp $	*/
2
3/*
4 * Copyright (c) 2022 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/types.h>
20
21#include <stddef.h>
22
23#include <ber.h>
24#include <stdint.h>
25#include <stdlib.h>
26
27#include "application.h"
28#include "log.h"
29#include "snmpd.h"
30
31struct appl_varbind *appl_blocklist_response(size_t);
32void appl_blocklist_get(struct appl_backend *, int32_t, int32_t, const char *,
33    struct appl_varbind *);
34void appl_blocklist_getnext(struct appl_backend *, int32_t, int32_t,
35    const char *, struct appl_varbind *);
36
37struct appl_backend_functions appl_blocklist_functions = {
38	.ab_get = appl_blocklist_get,
39	.ab_getnext = appl_blocklist_getnext,
40	.ab_getbulk = NULL,
41};
42
43struct appl_backend appl_blocklist = {
44	.ab_name = "blocklist",
45	.ab_cookie = NULL,
46	.ab_retries = 0,
47	.ab_fn = &appl_blocklist_functions
48};
49
50static struct appl_varbind *response = NULL;
51static size_t responsesz = 0;
52
53struct appl_varbind *
54appl_blocklist_response(size_t nvarbind)
55{
56	struct appl_varbind *tmp;
57	size_t i;
58
59	if (responsesz < nvarbind) {
60		if ((tmp = recallocarray(response, responsesz, nvarbind,
61		    sizeof(*response))) == NULL) {
62			log_warn(NULL);
63			return NULL;
64		}
65		responsesz = nvarbind;
66		response = tmp;
67	}
68	for (i = 0; i < nvarbind; i++)
69		response[i].av_next = i + 1 == nvarbind ?
70		    NULL : &(response[i + 1]);
71	return response;
72}
73
74void
75appl_blocklist_init(void)
76{
77	extern struct snmpd *snmpd_env;
78	size_t i;
79
80	for (i = 0; i < snmpd_env->sc_nblocklist; i++)
81		appl_register(NULL, 150, 1, &(snmpd_env->sc_blocklist[i]),
82		    0, 1, 0, 0, &appl_blocklist);
83}
84
85void
86appl_blocklist_shutdown(void)
87{
88	appl_close(&appl_blocklist);
89	free(response);
90}
91
92void
93appl_blocklist_get(struct appl_backend *backend, __unused int32_t transactionid,
94    int32_t requestid, __unused const char *ctx, struct appl_varbind *vblist)
95{
96	struct appl_varbind *vb, *rvb, *rvblist;
97	size_t i;
98
99	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next)
100		i++;
101	if ((rvblist = appl_blocklist_response(i)) == NULL)
102		goto fail;
103	rvb = rvblist;
104	for (vb = vblist; vb != NULL; vb = vb->av_next, rvb = rvb->av_next) {
105		rvb->av_oid = vb->av_oid;
106		rvb->av_value = appl_exception(APPL_EXC_NOSUCHOBJECT);
107		if (rvb->av_value == NULL)
108			goto fail;
109	}
110
111	appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, rvblist);
112	return;
113 fail:
114	for (rvb = rvblist; rvb != NULL && rvb->av_value != NULL;
115	    rvb = rvb->av_next)
116		ober_free_elements(rvb->av_value);
117	appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vb);
118}
119
120void
121appl_blocklist_getnext(struct appl_backend *backend,
122    __unused int32_t transactionid, int32_t requestid, __unused const char *ctx,
123    struct appl_varbind *vblist)
124{
125	struct appl_varbind *vb, *rvb, *rvblist;
126	size_t i;
127
128	for (i = 0, vb = vblist; vb != NULL; vb = vb->av_next)
129		i++;
130	if ((rvblist = appl_blocklist_response(i)) == NULL)
131		goto fail;
132	rvb = rvblist;
133	for (vb = vblist; vb != NULL; vb = vb->av_next, rvb = rvb->av_next) {
134		rvb->av_oid = vb->av_oid;
135		rvb->av_value = appl_exception(APPL_EXC_ENDOFMIBVIEW);
136		if (rvb->av_value == NULL)
137			goto fail;
138	}
139
140	appl_response(backend, requestid, APPL_ERROR_NOERROR, 0, rvblist);
141	return;
142 fail:
143	for (rvb = rvblist; rvb != NULL && rvb->av_value != NULL;
144	    rvb = rvb->av_next)
145		ober_free_elements(rvb->av_value);
146	appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vb);
147}
148