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 
31 struct appl_varbind *appl_blocklist_response(size_t);
32 void appl_blocklist_get(struct appl_backend *, int32_t, int32_t, const char *,
33     struct appl_varbind *);
34 void appl_blocklist_getnext(struct appl_backend *, int32_t, int32_t,
35     const char *, struct appl_varbind *);
36 
37 struct appl_backend_functions appl_blocklist_functions = {
38 	.ab_get = appl_blocklist_get,
39 	.ab_getnext = appl_blocklist_getnext,
40 	.ab_getbulk = NULL,
41 };
42 
43 struct appl_backend appl_blocklist = {
44 	.ab_name = "blocklist",
45 	.ab_cookie = NULL,
46 	.ab_retries = 0,
47 	.ab_fn = &appl_blocklist_functions
48 };
49 
50 static struct appl_varbind *response = NULL;
51 static size_t responsesz = 0;
52 
53 struct appl_varbind *
appl_blocklist_response(size_t nvarbind)54 appl_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 
74 void
appl_blocklist_init(void)75 appl_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 
85 void
appl_blocklist_shutdown(void)86 appl_blocklist_shutdown(void)
87 {
88 	appl_close(&appl_blocklist);
89 	free(response);
90 }
91 
92 void
appl_blocklist_get(struct appl_backend * backend,__unused int32_t transactionid,int32_t requestid,__unused const char * ctx,struct appl_varbind * vblist)93 appl_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 
120 void
appl_blocklist_getnext(struct appl_backend * backend,__unused int32_t transactionid,int32_t requestid,__unused const char * ctx,struct appl_varbind * vblist)121 appl_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