clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name main.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.bin/netstat/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/netstat/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.bin/netstat/main.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | #include <sys/types.h> |
34 | #include <sys/protosw.h> |
35 | #include <sys/socket.h> |
36 | #include <sys/sysctl.h> |
37 | |
38 | #include <net/route.h> |
39 | #include <netinet/in.h> |
40 | |
41 | #include <ctype.h> |
42 | #include <err.h> |
43 | #include <errno.h> |
44 | #include <fcntl.h> |
45 | #include <kvm.h> |
46 | #include <limits.h> |
47 | #include <netdb.h> |
48 | #include <nlist.h> |
49 | #include <paths.h> |
50 | #include <stdio.h> |
51 | #include <stdlib.h> |
52 | #include <string.h> |
53 | #include <unistd.h> |
54 | #include "netstat.h" |
55 | |
56 | struct nlist nl[] = { |
57 | #define N_AFMAP 0 |
58 | { "_afmap"}, |
59 | #define N_AF2IDX 1 |
60 | { "_af2idx" }, |
61 | #define N_AF2IDXMAX 2 |
62 | { "_af2idx_max" }, |
63 | |
64 | { "" } |
65 | }; |
66 | |
67 | struct protox { |
68 | void (*pr_stats)(char *); |
69 | char *pr_name; |
70 | int pr_proto; |
71 | } protox[] = { |
72 | { ip_stats, "ip", IPPROTO_IPV4 }, |
73 | { icmp_stats, "icmp", 0 }, |
74 | { igmp_stats, "igmp", 0 }, |
75 | { ipip_stats, "ipencap", 0 }, |
76 | { tcp_stats, "tcp", IPPROTO_TCP }, |
77 | { udp_stats, "udp", IPPROTO_UDP }, |
78 | { ipsec_stats, "ipsec", 0 }, |
79 | { esp_stats, "esp", 0 }, |
80 | { ah_stats, "ah", 0 }, |
81 | { etherip_stats,"etherip", 0 }, |
82 | { ipcomp_stats, "ipcomp", 0 }, |
83 | { carp_stats, "carp", 0 }, |
84 | { pfsync_stats, "pfsync", 0 }, |
85 | { div_stats, "divert", IPPROTO_DIVERT }, |
86 | { pflow_stats, "pflow", 0 }, |
87 | { NULL, NULL, 0 } |
88 | }; |
89 | |
90 | struct protox ip6protox[] = { |
91 | { ip6_stats, "ip6", IPPROTO_IPV6 }, |
92 | { div6_stats, "divert6", IPPROTO_DIVERT }, |
93 | { icmp6_stats, "icmp6", 0 }, |
94 | { rip6_stats, "rip6", 0 }, |
95 | { NULL, NULL, 0 } |
96 | }; |
97 | |
98 | struct protox *protoprotox[] = { |
99 | protox, ip6protox, NULL |
100 | }; |
101 | |
102 | static void usage(void); |
103 | static struct protox *name2protox(char *); |
104 | static struct protox *knownname(char *); |
105 | void gettable(u_int); |
106 | |
107 | kvm_t *kvmd; |
108 | |
109 | int Aflag; |
110 | int aflag; |
111 | int Bflag; |
112 | int bflag; |
113 | int dflag; |
114 | int Fflag; |
115 | int gflag; |
116 | int hflag; |
117 | int iflag; |
118 | int lflag; |
119 | |
120 | int mflag; |
121 | int nflag; |
122 | int pflag; |
123 | int Pflag; |
124 | int qflag; |
125 | int rflag; |
126 | int Rflag; |
127 | int sflag; |
128 | int tflag; |
129 | int vflag; |
130 | int Wflag; |
131 | |
132 | int interval; |
133 | |
134 | char *interface; |
135 | |
136 | int af; |
137 | |
138 | int |
139 | main(int argc, char *argv[]) |
140 | { |
141 | extern char *optarg; |
142 | extern int optind; |
143 | const char *errstr; |
144 | struct protox *tp = NULL; |
| 1 | 'tp' initialized to a null pointer value | |
|
145 | int ch; |
146 | char *nlistf = NULL, *memf = NULL, *ep; |
147 | char buf[_POSIX2_LINE_MAX]; |
148 | u_long pcbaddr = 0; |
149 | u_int tableid; |
150 | int Tflag = 0; |
151 | int repeatcount = 0; |
152 | int proto = 0; |
153 | int need_nlist, kvm_flags = O_RDONLY; |
154 | |
155 | af = AF_UNSPEC; |
156 | tableid = getrtable(); |
157 | |
158 | while ((ch = getopt(argc, argv, |
| 2 | | Assuming the condition is false | |
|
| 3 | | Loop condition is false. Execution continues on line 295 | |
|
159 | "AaBbc:deFf:ghI:iLlM:mN:np:P:qRrsT:tuvW:w:")) != -1) |
160 | switch (ch) { |
161 | case 'A': |
162 | Aflag = 1; |
163 | break; |
164 | case 'a': |
165 | aflag = 1; |
166 | break; |
167 | case 'B': |
168 | Bflag = 1; |
169 | break; |
170 | case 'b': |
171 | bflag = 1; |
172 | break; |
173 | case 'c': |
174 | repeatcount = strtonum(optarg, 1, INT_MAX, &errstr); |
175 | if (errstr) |
176 | errx(1, "count is %s", errstr); |
177 | break; |
178 | case 'd': |
179 | dflag = IF_SHOW_DROP; |
180 | break; |
181 | case 'e': |
182 | dflag = IF_SHOW_ERRS; |
183 | break; |
184 | case 'F': |
185 | Fflag = 1; |
186 | break; |
187 | case 'f': |
188 | if (strcmp(optarg, "inet") == 0) |
189 | af = AF_INET; |
190 | else if (strcmp(optarg, "inet6") == 0) |
191 | af = AF_INET6; |
192 | else if (strcmp(optarg, "local") == 0) |
193 | af = AF_LOCAL; |
194 | else if (strcmp(optarg, "unix") == 0) |
195 | af = AF_UNIX; |
196 | else if (strcmp(optarg, "mpls") == 0) |
197 | af = AF_MPLS; |
198 | else { |
199 | (void)fprintf(stderr, |
200 | "%s: %s: unknown address family\n", |
201 | __progname, optarg); |
202 | exit(1); |
203 | } |
204 | break; |
205 | case 'g': |
206 | gflag = 1; |
207 | break; |
208 | case 'h': |
209 | hflag = 1; |
210 | break; |
211 | case 'I': |
212 | iflag = 1; |
213 | interface = optarg; |
214 | break; |
215 | case 'i': |
216 | iflag = 1; |
217 | break; |
218 | case 'l': |
219 | lflag = 1; |
220 | break; |
221 | case 'M': |
222 | memf = optarg; |
223 | break; |
224 | case 'm': |
225 | mflag = 1; |
226 | break; |
227 | case 'N': |
228 | nlistf = optarg; |
229 | break; |
230 | case 'n': |
231 | nflag = 1; |
232 | break; |
233 | case 'p': |
234 | if ((tp = name2protox(optarg)) == NULL) { |
235 | (void)fprintf(stderr, |
236 | "%s: %s: unknown protocol\n", |
237 | __progname, optarg); |
238 | exit(1); |
239 | } |
240 | pflag = 1; |
241 | break; |
242 | case 'P': |
243 | errno = 0; |
244 | pcbaddr = strtoul(optarg, &ep, 16); |
245 | if (optarg[0] == '\0' || *ep != '\0' || |
246 | errno == ERANGE) { |
247 | (void)fprintf(stderr, |
248 | "%s: %s: invalid PCB address\n", |
249 | __progname, optarg); |
250 | exit(1); |
251 | } |
252 | Pflag = 1; |
253 | break; |
254 | case 'q': |
255 | qflag = 1; |
256 | break; |
257 | case 'R': |
258 | Rflag = 1; |
259 | break; |
260 | case 'r': |
261 | rflag = 1; |
262 | break; |
263 | case 's': |
264 | ++sflag; |
265 | break; |
266 | case 'T': |
267 | tableid = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr); |
268 | if (errstr) |
269 | errx(1, "invalid table id: %s", errstr); |
270 | Tflag = 1; |
271 | break; |
272 | case 't': |
273 | tflag = 1; |
274 | break; |
275 | case 'u': |
276 | af = AF_UNIX; |
277 | break; |
278 | case 'v': |
279 | vflag = 1; |
280 | break; |
281 | case 'W': |
282 | Wflag = 1; |
283 | interface = optarg; |
284 | break; |
285 | case 'w': |
286 | interval = strtonum(optarg, 1, INT_MAX, &errstr); |
287 | if (errstr) |
288 | errx(1, "interval is %s", errstr); |
289 | iflag = 1; |
290 | break; |
291 | case '?': |
292 | default: |
293 | usage(); |
294 | } |
295 | argv += optind; |
296 | argc -= optind; |
297 | |
298 | if (argc) { |
| |
| |
299 | interval = strtonum(*argv, 1, INT_MAX, &errstr); |
300 | if (errstr) |
301 | errx(1, "interval is %s", errstr); |
302 | ++argv; |
303 | --argc; |
304 | iflag = 1; |
305 | } |
306 | if (argc) |
| |
307 | usage(); |
308 | |
309 | |
310 | |
311 | |
312 | |
313 | if (Wflag) { |
| |
| |
314 | if (interface == NULL) |
315 | usage(); |
316 | net80211_ifstats(interface); |
317 | exit(0); |
318 | } |
319 | |
320 | if (mflag) { |
| |
| |
321 | mbpr(); |
322 | exit(0); |
323 | } |
324 | if (iflag) { |
| |
| |
325 | intpr(interval, repeatcount); |
326 | exit(0); |
327 | } |
328 | if (sflag) { |
| |
| |
329 | if (rflag) { |
330 | rt_stats(); |
331 | } else if (gflag) { |
332 | if (af == AF_INET || af == AF_UNSPEC) |
333 | mrt_stats(); |
334 | if (af == AF_INET6 || af == AF_UNSPEC) |
335 | mrt6_stats(); |
336 | } else if (pflag && tp->pr_name) { |
337 | (*tp->pr_stats)(tp->pr_name); |
338 | } else { |
339 | if (af == AF_INET || af == AF_UNSPEC) |
340 | for (tp = protox; tp->pr_name; tp++) |
341 | (*tp->pr_stats)(tp->pr_name); |
342 | if (af == AF_INET6 || af == AF_UNSPEC) |
343 | for (tp = ip6protox; tp->pr_name; tp++) |
344 | (*tp->pr_stats)(tp->pr_name); |
345 | } |
346 | exit(0); |
347 | } |
348 | if (gflag) { |
| |
| |
349 | if (af == AF_INET || af == AF_UNSPEC) |
350 | mroutepr(); |
351 | if (af == AF_INET6 || af == AF_UNSPEC) |
352 | mroute6pr(); |
353 | exit(0); |
354 | } |
355 | |
356 | if (Rflag) { |
| |
| |
357 | rdomainpr(); |
358 | exit(0); |
359 | } |
360 | |
361 | |
362 | |
363 | |
364 | |
365 | need_nlist = (nlistf != NULL) || (memf != NULL) || (Aflag && rflag); |
| |
366 | if (!need_nlist && !Pflag) |
| 20 | | Assuming 'Pflag' is not equal to 0 | |
|
| |
367 | kvm_flags |= KVM_NO_FILES; |
368 | |
369 | if ((kvmd = kvm_openfiles(nlistf, memf, NULL, kvm_flags, buf)) == NULL) |
| 22 | | Assuming the condition is false | |
|
| |
370 | errx(1, "kvm_openfiles: %s", buf); |
371 | |
372 | if (need_nlist && (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0)) { |
373 | if (nlistf) |
374 | errx(1, "%s: no namelist", nlistf); |
375 | else |
376 | errx(1, "no namelist"); |
377 | } |
378 | |
379 | if (!need_nlist && Tflag) |
| |
380 | gettable(tableid); |
381 | |
382 | if (rflag) { |
| |
| |
383 | if (Aflag || nlistf != NULL || memf != NULL) |
384 | routepr(nl[N_AFMAP].n_value, nl[N_AF2IDX].n_value, |
385 | nl[N_AF2IDXMAX].n_value, tableid); |
386 | else |
387 | p_rttables(af, tableid); |
388 | exit(0); |
389 | } |
390 | |
391 | if (pflag) { |
| 27 | | Assuming 'pflag' is not equal to 0 | |
|
| |
392 | if (tp->pr_proto == 0) |
| 29 | | Access to field 'pr_proto' results in a dereference of a null pointer (loaded from variable 'tp') |
|
393 | errx(1, "no protocol handler for protocol %s", |
394 | tp->pr_name); |
395 | else |
396 | proto = tp->pr_proto; |
397 | } |
398 | |
399 | protopr(kvmd, pcbaddr, tableid, proto); |
400 | exit(0); |
401 | } |
402 | |
403 | |
404 | |
405 | |
406 | int |
407 | kread(u_long addr, void *buf, int size) |
408 | { |
409 | |
410 | if (kvm_read(kvmd, addr, buf, size) != size) { |
411 | (void)fprintf(stderr, "%s: %s\n", __progname, |
412 | kvm_geterr(kvmd)); |
413 | return (-1); |
414 | } |
415 | return (0); |
416 | } |
417 | |
418 | char * |
419 | plural(u_int64_t n) |
420 | { |
421 | return (n != 1 ? "s" : ""); |
422 | } |
423 | |
424 | char * |
425 | plurales(u_int64_t n) |
426 | { |
427 | return (n != 1 ? "es" : ""); |
428 | } |
429 | |
430 | char * |
431 | pluralys(u_int64_t n) |
432 | { |
433 | return (n != 1 ? "ies" : "y"); |
434 | } |
435 | |
436 | |
437 | |
438 | |
439 | static struct protox * |
440 | knownname(char *name) |
441 | { |
442 | struct protox **tpp, *tp; |
443 | |
444 | for (tpp = protoprotox; *tpp; tpp++) |
445 | for (tp = *tpp; tp->pr_name; tp++) |
446 | if (strcmp(tp->pr_name, name) == 0) |
447 | return (tp); |
448 | return (NULL); |
449 | } |
450 | |
451 | |
452 | |
453 | |
454 | static struct protox * |
455 | name2protox(char *name) |
456 | { |
457 | struct protox *tp; |
458 | char **alias; |
459 | struct protoent *p; |
460 | |
461 | |
462 | |
463 | |
464 | |
465 | if ((tp = knownname(name))) |
466 | return (tp); |
467 | |
468 | setprotoent(1); |
469 | while ((p = getprotoent())) { |
470 | |
471 | for (alias = p->p_aliases; *alias; alias++) |
472 | if (strcmp(name, *alias) == 0) { |
473 | endprotoent(); |
474 | return (knownname(p->p_name)); |
475 | } |
476 | } |
477 | endprotoent(); |
478 | return (NULL); |
479 | } |
480 | |
481 | static void |
482 | usage(void) |
483 | { |
484 | (void)fprintf(stderr, |
485 | "usage: netstat [-AaBln] [-M core] [-N system] [-p protocol] [-T rtable]\n" |
486 | " netstat -W interface\n" |
487 | " netstat -m\n" |
488 | " netstat -I interface | -i [-bdehnqt]\n" |
489 | " netstat -w wait [-bdehnqt] [-c count] [-I interface]\n" |
490 | " netstat -s [-gru] [-f address_family] [-p protocol]\n" |
491 | " netstat -g [-lnu] [-f address_family]\n" |
492 | " netstat -R\n" |
493 | " netstat -r [-AFu] [-f address_family] [-M core] [-N system] [-p protocol]\n" |
494 | " [-T rtable]\n" |
495 | " netstat -P pcbaddr [-v] [-M core] [-N system]\n"); |
496 | exit(1); |
497 | } |
498 | |
499 | void |
500 | gettable(u_int tableid) |
501 | { |
502 | struct rt_tableinfo info; |
503 | int mib[6]; |
504 | size_t len; |
505 | |
506 | mib[0] = CTL_NET; |
507 | mib[1] = PF_ROUTE; |
508 | mib[2] = 0; |
509 | mib[3] = 0; |
510 | mib[4] = NET_RT_TABLE; |
511 | mib[5] = tableid; |
512 | |
513 | len = sizeof(info); |
514 | if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) |
515 | err(1, "routing table %d", tableid); |
516 | } |