Bug Summary

File:src/usr.sbin/snmpd/snmpd.c
Warning:line 198, column 2
Value stored to 'argv' is never read

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 snmpd.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/snmpd.c
1/* $OpenBSD: snmpd.c,v 1.46 2021/08/10 06:52:03 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/types.h>
20#include <sys/queue.h>
21#include <sys/socket.h>
22#include <sys/wait.h>
23#include <sys/tree.h>
24
25#include <net/if.h>
26
27#include <string.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <getopt.h>
31#include <err.h>
32#include <errno(*__errno()).h>
33#include <event.h>
34#include <signal.h>
35#include <syslog.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include <pwd.h>
39
40#include "snmpd.h"
41#include "mib.h"
42
43__dead__attribute__((__noreturn__)) void usage(void);
44
45void snmpd_shutdown(struct snmpd *);
46void snmpd_sig_handler(int, short, void *);
47int snmpd_dispatch_snmpe(int, struct privsep_proc *, struct imsg *);
48int check_child(pid_t, const char *);
49
50struct snmpd *snmpd_env;
51
52static struct privsep_proc procs[] = {
53 { "snmpe", PROC_SNMPE, snmpd_dispatch_snmpe, snmpe, snmpe_shutdown },
54};
55
56enum privsep_procid privsep_process;
57
58void
59snmpd_sig_handler(int sig, short event, void *arg)
60{
61 struct privsep *ps = arg;
62 struct snmpd *env = ps->ps_env;
63 int die = 0, status, fail, id;
64 pid_t pid;
65 char *cause;
66
67 switch (sig) {
68 case SIGTERM15:
69 case SIGINT2:
70 die = 1;
71 /* FALLTHROUGH */
72 case SIGCHLD20:
73 do {
74 int len;
75
76 pid = waitpid(WAIT_ANY(-1), &status, WNOHANG1);
77 if (pid <= 0)
78 continue;
79
80 fail = 0;
81 if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
) {
82 fail = 1;
83 len = asprintf(&cause, "terminated; signal %d",
84 WTERMSIG(status)(((status) & 0177)));
85 } else if (WIFEXITED(status)(((status) & 0177) == 0)) {
86 if (WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff) != 0) {
87 fail = 1;
88 len = asprintf(&cause,
89 "exited abnormally");
90 } else
91 len = asprintf(&cause, "exited okay");
92 } else
93 fatalx("unexpected cause of SIGCHLD");
94
95 if (len == -1)
96 fatal("asprintf");
97
98 for (id = 0; id < PROC_MAX; id++) {
99 if (pid == ps->ps_pid[id] &&
100 check_child(ps->ps_pid[id],
101 ps->ps_title[id])) {
102 die = 1;
103 if (fail)
104 log_warnx("lost child: %s %s",
105 ps->ps_title[id], cause);
106 break;
107 }
108 }
109 free(cause);
110 } while (pid > 0 || (pid == -1 && errno(*__errno()) == EINTR4));
111
112 if (die)
113 snmpd_shutdown(env);
114 break;
115 case SIGHUP1:
116 /* reconfigure */
117 break;
118 case SIGUSR130:
119 /* ignore */
120 break;
121 default:
122 fatalx("unexpected signal");
123 }
124}
125
126__dead__attribute__((__noreturn__)) void
127usage(void)
128{
129 extern char *__progname;
130
131 fprintf(stderr(&__sF[2]), "usage: %s [-dNnv] [-D macro=value] "
132 "[-f file]\n", __progname);
133 exit(1);
134}
135
136int
137main(int argc, char *argv[])
138{
139 int c;
140 struct snmpd *env;
141 int debug = 0, verbose = 0;
142 u_int flags = 0;
143 int noaction = 0;
144 const char *conffile = CONF_FILE"/etc/snmpd.conf";
145 struct privsep *ps;
146 int proc_id = PROC_PARENT, proc_instance = 0;
147 int argc0 = argc;
148 char **argv0 = argv;
149 const char *errp, *title = NULL((void *)0);
150
151 smi_init();
152
153 /* log to stderr until daemonized */
154 log_init(1, LOG_DAEMON(3<<3));
155
156 while ((c = getopt(argc, argv, "dD:nNf:I:P:v")) != -1) {
157 switch (c) {
158 case 'd':
159 debug++;
160 flags |= SNMPD_F_DEBUG0x02;
161 break;
162 case 'D':
163 if (cmdline_symset(optarg) < 0)
164 log_warnx("could not parse macro definition %s",
165 optarg);
166 break;
167 case 'n':
168 noaction = 1;
169 break;
170 case 'N':
171 flags |= SNMPD_F_NONAMES0x04;
172 break;
173 case 'f':
174 conffile = optarg;
175 break;
176 case 'I':
177 proc_instance = strtonum(optarg, 0,
178 PROC_MAX_INSTANCES32, &errp);
179 if (errp)
180 fatalx("invalid process instance");
181 break;
182 case 'P':
183 title = optarg;
184 proc_id = proc_getid(procs, nitems(procs)(sizeof((procs)) / sizeof((procs)[0])), title);
185 if (proc_id == PROC_MAX)
186 fatalx("invalid process name");
187 break;
188 case 'v':
189 verbose++;
190 flags |= SNMPD_F_VERBOSE0x01;
191 break;
192 default:
193 usage();
194 }
195 }
196
197 argc -= optind;
198 argv += optind;
Value stored to 'argv' is never read
199 if (argc > 0)
200 usage();
201
202 if ((env = parse_config(conffile, flags)) == NULL((void *)0))
203 exit(1);
204
205 ps = &env->sc_ps;
206 ps->ps_env = env;
207 snmpd_env = env;
208 ps->ps_instance = proc_instance;
209 if (title)
210 ps->ps_title[proc_id] = title;
211
212 if (noaction) {
213 fprintf(stderr(&__sF[2]), "configuration ok\n");
214 exit(0);
215 }
216
217 if (geteuid())
218 errx(1, "need root privileges");
219
220 if ((ps->ps_pw = getpwnam(SNMPD_USER"_snmpd")) == NULL((void *)0))
221 errx(1, "unknown user %s", SNMPD_USER"_snmpd");
222
223 log_init(debug, LOG_DAEMON(3<<3));
224 log_setverbose(verbose);
225
226 gettimeofday(&env->sc_starttime, NULL((void *)0));
227 env->sc_engine_boots = 0;
228
229 pf_init();
230
231 proc_init(ps, procs, nitems(procs)(sizeof((procs)) / sizeof((procs)[0])), debug, argc0, argv0, proc_id);
232 if (!debug && daemon(0, 0) == -1)
233 err(1, "failed to daemonize");
234
235 log_procinit("parent");
236 log_info("startup");
237
238 event_init();
239
240 signal_set(&ps->ps_evsigint, SIGINT, snmpd_sig_handler, ps)event_set(&ps->ps_evsigint, 2, 0x08|0x10, snmpd_sig_handler
, ps)
;
241 signal_set(&ps->ps_evsigterm, SIGTERM, snmpd_sig_handler, ps)event_set(&ps->ps_evsigterm, 15, 0x08|0x10, snmpd_sig_handler
, ps)
;
242 signal_set(&ps->ps_evsigchld, SIGCHLD, snmpd_sig_handler, ps)event_set(&ps->ps_evsigchld, 20, 0x08|0x10, snmpd_sig_handler
, ps)
;
243 signal_set(&ps->ps_evsighup, SIGHUP, snmpd_sig_handler, ps)event_set(&ps->ps_evsighup, 1, 0x08|0x10, snmpd_sig_handler
, ps)
;
244 signal_set(&ps->ps_evsigpipe, SIGPIPE, snmpd_sig_handler, ps)event_set(&ps->ps_evsigpipe, 13, 0x08|0x10, snmpd_sig_handler
, ps)
;
245 signal_set(&ps->ps_evsigusr1, SIGUSR1, snmpd_sig_handler, ps)event_set(&ps->ps_evsigusr1, 30, 0x08|0x10, snmpd_sig_handler
, ps)
;
246
247 signal_add(&ps->ps_evsigint, NULL)event_add(&ps->ps_evsigint, ((void *)0));
248 signal_add(&ps->ps_evsigterm, NULL)event_add(&ps->ps_evsigterm, ((void *)0));
249 signal_add(&ps->ps_evsigchld, NULL)event_add(&ps->ps_evsigchld, ((void *)0));
250 signal_add(&ps->ps_evsighup, NULL)event_add(&ps->ps_evsighup, ((void *)0));
251 signal_add(&ps->ps_evsigpipe, NULL)event_add(&ps->ps_evsigpipe, ((void *)0));
252 signal_add(&ps->ps_evsigusr1, NULL)event_add(&ps->ps_evsigusr1, ((void *)0));
253
254 proc_connect(ps);
255
256 if (pledge("stdio dns sendfd proc exec id", NULL((void *)0)) == -1)
257 fatal("pledge");
258
259 event_dispatch();
260
261 log_debug("%d parent exiting", getpid());
262
263 return (0);
264}
265
266void
267snmpd_shutdown(struct snmpd *env)
268{
269 proc_kill(&env->sc_ps);
270
271 free(env);
272
273 log_info("terminating");
274 exit(0);
275}
276
277int
278check_child(pid_t pid, const char *pname)
279{
280 int status;
281
282 if (waitpid(pid, &status, WNOHANG1) > 0) {
283 if (WIFEXITED(status)(((status) & 0177) == 0)) {
284 log_warnx("check_child: lost child: %s exited", pname);
285 return (1);
286 }
287 if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
) {
288 log_warnx("check_child: lost child: %s terminated; "
289 "signal %d", pname, WTERMSIG(status)(((status) & 0177)));
290 return (1);
291 }
292 }
293
294 return (0);
295}
296
297int
298snmpd_dispatch_snmpe(int fd, struct privsep_proc *p, struct imsg *imsg)
299{
300 switch (imsg->hdr.type) {
301 case IMSG_TRAP_EXEC:
302 return (traphandler_priv_recvmsg(p, imsg));
303 case IMSG_CTL_RELOAD:
304 /* XXX notyet */
305 default:
306 break;
307 }
308
309 return (-1);
310}
311
312int
313snmpd_socket_af(struct sockaddr_storage *ss, int type)
314{
315 int fd, serrno;
316 const int enable = 1;
317
318 fd = socket(ss->ss_family, (type == SOCK_STREAM1 ?
319 SOCK_STREAM1 | SOCK_NONBLOCK0x4000 : SOCK_DGRAM2) | SOCK_CLOEXEC0x8000, 0);
320 if (fd == -1)
321 return -1;
322
323 if (setsockopt(fd, SOL_SOCKET0xffff, SO_REUSEADDR0x0004, &enable,
324 sizeof(enable)) == -1) {
325 serrno = errno(*__errno());
326 close(fd);
327 errno(*__errno()) = serrno;
328 return -1;
329 }
330 return fd;
331}
332
333u_long
334snmpd_engine_time(void)
335{
336 struct timeval now;
337
338 /*
339 * snmpEngineBoots should be stored in a non-volatile storage.
340 * snmpEngineTime is the number of seconds since snmpEngineBoots
341 * was last incremented. We don't rely on non-volatile storage.
342 * snmpEngineBoots is set to zero and snmpEngineTime to the system
343 * clock. Hence, the tuple (snmpEngineBoots, snmpEngineTime) is
344 * still unique and protects us against replay attacks. It only
345 * 'expires' a little bit sooner than the RFC3414 method.
346 */
347 gettimeofday(&now, NULL((void *)0));
348 return now.tv_sec;
349}