Bug Summary

File:src/usr.sbin/snmpd/mps.c
Warning:line 251, column 8
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mps.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/snmpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/snmpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/snmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/snmpd/mps.c
1/* $OpenBSD: mps.c,v 1.29 2020/06/30 17:11:49 martijn Exp $ */
2
3/*
4 * Copyright (c) 2007, 2008, 2012 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/queue.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <sys/socket.h>
23#include <sys/un.h>
24#include <sys/tree.h>
25#include <sys/sysctl.h>
26
27#include <net/if.h>
28#include <net/if_dl.h>
29#include <net/if_arp.h>
30#include <net/if_media.h>
31#include <net/route.h>
32#include <netinet/in.h>
33#include <netinet/if_ether.h>
34#include <arpa/inet.h>
35
36#include <stdlib.h>
37#include <stdio.h>
38#include <errno(*__errno()).h>
39#include <event.h>
40#include <fcntl.h>
41#include <string.h>
42#include <unistd.h>
43#include <pwd.h>
44
45#include "snmpd.h"
46#include "mib.h"
47
48struct ber_oid *
49 mps_table(struct oid *, struct ber_oid *, struct ber_oid *);
50
51int
52mps_getstr(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
53{
54 char *s = oid->o_data;
55
56 if (s == NULL((void *)0))
57 return (-1);
58 *elm = ober_add_string(*elm, s);
59 return (0);
60}
61
62int
63mps_setstr(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
64{
65 struct ber_element *ber = *elm;
66 char *s, *v;
67
68 if ((oid->o_flags & OID_WR0x02) == 0)
69 return (-1);
70
71 if (ber->be_class != BER_CLASS_UNIVERSAL0x0 ||
72 ber->be_type != BER_TYPE_OCTETSTRING4)
73 return (-1);
74 if (ober_get_string(ber, &s) == -1)
75 return (-1);
76 if ((v = (void *)strdup(s)) == NULL((void *)0))
77 return (-1);
78 free(oid->o_data);
79 oid->o_data = v;
80 oid->o_val = strlen(v);
81
82 return (0);
83}
84
85int
86mps_getint(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
87{
88 *elm = ober_add_integer(*elm, oid->o_val);
89 return (0);
90}
91
92int
93mps_setint(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
94{
95 long long i;
96
97 if (ober_get_integer(*elm, &i) == -1)
98 return (-1);
99 oid->o_val = i;
100
101 return (0);
102}
103
104int
105mps_getts(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
106{
107 *elm = ober_add_integer(*elm, oid->o_val);
108 ober_set_header(*elm, BER_CLASS_APPLICATION0x1, SNMP_T_TIMETICKS);
109 return (0);
110}
111
112int
113mps_getreq(struct snmp_message *msg, struct ber_element *root,
114 struct ber_oid *o, u_int sm_version)
115{
116 struct ber_element *elm = root;
117 struct oid key, *value;
118 unsigned long error_type = 0; /* noSuchObject */
119
120 if (o->bo_n > BER_MAX_OID_LEN128)
121 return (-1);
122 bzero(&key, sizeof(key));
123 bcopy(o, &key.o_id, sizeof(struct ber_oid));
124 smi_oidlen(&key.o_id); /* Strip off any trailing .0. */
125 value = smi_find(&key);
126 if (value == NULL((void *)0))
127 goto fail;
128
129 if (OID_NOTSET(value)(((value)->o_flags & 0x04) && ((value)->o_data
== ((void *)0)) && ((value)->o_val == 0))
)
130 goto fail;
131
132 if (value->o_get == NULL((void *)0))
133 goto fail;
134
135 if (value->o_oidleno_id.bo_n == o->bo_n) {
136 /* No instance identifier specified. */
137 error_type = 1; /* noSuchInstance */
138 goto fail;
139 }
140
141 if ((value->o_flags & OID_TABLE0x10) == 0)
142 elm = ober_add_oid(elm, o);
143 if (value->o_get(value, o, &elm) != 0)
144 goto fail;
145
146 return (0);
147
148fail:
149 if (sm_version == 0)
150 return (-1);
151
152 /* Set SNMPv2 extended error response. */
153 elm = ober_add_oid(elm, o);
154 elm = ober_add_null(elm);
155 ober_set_header(elm, BER_CLASS_CONTEXT0x2, error_type);
156 return (0);
157}
158
159int
160mps_setreq(struct snmp_message *msg, struct ber_element *ber,
161 struct ber_oid *o)
162{
163 struct oid key, *value;
164
165 smi_oidlen(o);
166 if (o->bo_n > BER_MAX_OID_LEN128)
167 return (-1);
168 bzero(&key, sizeof(key));
169 bcopy(o, &key.o_id, sizeof(struct ber_oid));
170 value = smi_find(&key);
171 if (value == NULL((void *)0))
172 return (-1);
173 if ((value->o_flags & OID_WR0x02) == 0 ||
174 value->o_set == NULL((void *)0))
175 return (-1);
176 return (value->o_set(value, o, &ber));
177}
178
179int
180mps_getnextreq(struct snmp_message *msg, struct ber_element *root,
181 struct ber_oid *o)
182{
183 struct oid *next = NULL((void *)0);
184 struct ber_element *ber = root;
185 struct oid key, *value;
186 int ret;
187 struct ber_oid no;
188 unsigned long error_type = 0; /* noSuchObject */
189
190 if (o->bo_n > BER_MAX_OID_LEN128)
191 return (-1);
192 bzero(&key, sizeof(key));
193 bcopy(o, &key.o_id, sizeof(struct ber_oid));
194 smi_oidlen(&key.o_id); /* Strip off any trailing .0. */
195 value = smi_nfind(&key);
196 if (value == NULL((void *)0))
197 goto fail;
198
199 if (value->o_flags & OID_TABLE0x10) {
200 /* Get the next table row for this column */
201 if (mps_table(value, o, &no) != NULL((void *)0)) {
202 bcopy(&no, o, sizeof(*o));
203 ret = value->o_get(value, o, &ber);
204 } else
205 ret = 1;
206 switch (ret) {
207 case 0:
208 return (0);
209 case -1:
210 goto fail;
211 case 1: /* end-of-rows */
212 break;
213 }
214 } else if (o->bo_n == value->o_oidleno_id.bo_n && value->o_get != NULL((void *)0)) {
215 next = value;
216 goto appendzero;
217 }
218
219 getnext:
220 for (next = value; next != NULL((void *)0);) {
221 next = smi_next(next);
222 if (next == NULL((void *)0))
223 break;
224 if (!OID_NOTSET(next)(((next)->o_flags & 0x04) && ((next)->o_data
== ((void *)0)) && ((next)->o_val == 0))
&& next->o_get != NULL((void *)0))
225 break;
226 }
227 if (next == NULL((void *)0) || next->o_get == NULL((void *)0))
228 goto fail;
229
230 if (next->o_flags & OID_TABLE0x10) {
231 /* Get the next table row for this column */
232 if (mps_table(next, o, &no) == NULL((void *)0)) {
233 value = next;
234 goto getnext;
235 }
236 bcopy(&no, o, sizeof(*o));
237 if ((ret = next->o_get(next, o, &ber)) != 0) {
238 if (ret == 1) {
239 value = next;
240 goto getnext;
241 }
242 goto fail;
243 }
244 } else {
245 bcopy(&next->o_id, o, sizeof(*o));
246 appendzero:
247 /* No instance identifier specified. Append .0. */
248 if (o->bo_n + 1 > BER_MAX_OID_LEN128)
249 goto fail;
250 ber = ober_add_noid(ber, o, ++o->bo_n);
251 if ((ret = next->o_get(next, o, &ber)) != 0)
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'
252 goto fail;
253 }
254
255 return (0);
256
257fail:
258 if (msg->sm_version == 0)
259 return (-1);
260
261 /* Set SNMPv2 extended error response. */
262 ber = ober_add_oid(ber, o);
263 ber = ober_add_null(ber);
264 ober_set_header(ber, BER_CLASS_CONTEXT0x2, error_type);
265 return (0);
266}
267
268int
269mps_getbulkreq(struct snmp_message *msg, struct ber_element **root,
270 struct ber_element **end, struct ber_oid *o, int max)
271{
272 struct ber_element *c, *d, *e;
273 size_t len;
274 int j, ret;
275
276 j = max;
277 c = *root;
278 *end = NULL((void *)0);
279
280 for (d = NULL((void *)0), len = 0; j > 0; j--) {
281 e = ober_add_sequence(NULL((void *)0));
282 if (c == NULL((void *)0))
283 c = e;
284 ret = mps_getnextreq(msg, e, o);
285 if (ret == 1) {
286 *root = c;
287 return (1);
288 }
289 if (ret == -1) {
290 ober_free_elements(e);
291 if (d == NULL((void *)0))
292 return (-1);
293 break;
294 }
295 len += ober_calc_len(e);
296 if (len > SNMPD_MAXVARBINDLEN1210) {
297 ober_free_elements(e);
298 break;
299 }
300 if (d != NULL((void *)0))
301 ober_link_elements(d, e);
302 d = e;
303 *end = d;
304 }
305
306 *root = c;
307 return (0);
308}
309
310int
311mps_set(struct ber_oid *o, void *p, long long len)
312{
313 struct oid key, *value;
314
315 smi_oidlen(o);
316 if (o->bo_n > BER_MAX_OID_LEN128)
317 return (-1);
318 bzero(&key, sizeof(key));
319 bcopy(o, &key.o_id, sizeof(struct ber_oid));
320 value = smi_find(&key);
321 if (value == NULL((void *)0))
322 return (-1);
323 free(value->o_data);
324 value->o_data = p;
325 value->o_val = len;
326
327 return (0);
328}
329
330struct ber_oid *
331mps_table(struct oid *oid, struct ber_oid *o, struct ber_oid *no)
332{
333 u_int32_t col, idx = 1, id, subid;
334 struct oid a, b;
335
336 /*
337 * This function is being used to iterate through elements
338 * in a SMI "table". It is called by the mps_getnext() handler.
339 * For example, if the input is sysORIndex, it will return
340 * sysORIndex.1. If the input is sysORIndex.2, it will return
341 * sysORIndex.3 etc.. The MIB code has to verify the index,
342 * see mib_sysor() as an example.
343 */
344
345 if (oid->o_table != NULL((void *)0))
346 return (oid->o_table(oid, o, no));
347
348 bcopy(&oid->o_id, no, sizeof(*no));
349 id = oid->o_oidleno_id.bo_n - 1;
350 subid = oid->o_oidleno_id.bo_n;
351
352 if (o->bo_n >= oid->o_oidleno_id.bo_n) {
353 /*
354 * Compare the requested and the matched OID to see
355 * if we have to iterate to the next element.
356 */
357 bzero(&a, sizeof(a));
358 bcopy(o, &a.o_id, sizeof(struct ber_oid));
359 bzero(&b, sizeof(b));
360 bcopy(&oid->o_id, &b.o_id, sizeof(struct ber_oid));
361 b.o_oidleno_id.bo_n--;
362 b.o_flags |= OID_TABLE0x10;
363 if (smi_oid_cmp(&a, &b) == 0) {
364 col = oid->o_oido_id.bo_id[id];
365 if (col > o->bo_id[id])
366 idx = 1;
367 else
368 idx = o->bo_id[subid] + 1;
369 o->bo_id[subid] = idx;
370 o->bo_id[id] = col;
371 bcopy(o, no, sizeof(*no));
372 }
373 }
374
375 /* The root element ends with a 0, iterate to the first element */
376 if (!no->bo_id[subid])
377 no->bo_id[subid]++;
378
379 smi_oidlen(no);
380
381 return (no);
382}
383
384void
385mps_encodeinaddr(struct ber_oid *o, struct in_addr *addr, int offset)
386{
387 u_int32_t a, i;
388
389 o->bo_n = offset;
390 if (addr != NULL((void *)0)) {
391 a = htole32(addr->s_addr)((__uint32_t)(addr->s_addr));
392 o->bo_id[o->bo_n++] = a & 0xff;
393 o->bo_id[o->bo_n++] = (a >> 8) & 0xff;
394 o->bo_id[o->bo_n++] = (a >> 16) & 0xff;
395 o->bo_id[o->bo_n++] = (a >> 24) & 0xff;
396 } else {
397 /* Create an invalid "last address" marker (5 bytes) */
398 for (i = 0; i < 5; i++)
399 o->bo_id[o->bo_n++] = 0xff;
400 }
401}
402
403int
404mps_decodeinaddr(struct ber_oid *o, struct in_addr *addr, int offset)
405{
406 u_int32_t a;
407
408 a = ((o->bo_id[offset] & 0xff)) |
409 ((o->bo_id[offset + 1] & 0xff) << 8) |
410 ((o->bo_id[offset + 2] & 0xff) << 16) |
411 ((o->bo_id[offset + 3] & 0xff) << 24);
412 addr->s_addr = letoh32(a)((__uint32_t)(a));
413
414 /* Detect invalid address */
415 if ((o->bo_n - offset) > 4)
416 return (-1);
417
418 return (0);
419}