Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/netstat/main.c
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#ifdef NETGRAPH | #ifdef NETGRAPH | ||||
#include <netgraph/ng_socket.h> | #include <netgraph/ng_socket.h> | ||||
#endif | #endif | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <err.h> | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <kvm.h> | #include <kvm.h> | ||||
#include <limits.h> | #include <limits.h> | ||||
#include <netdb.h> | #include <netdb.h> | ||||
#include <nlist.h> | #include <nlist.h> | ||||
#include <paths.h> | #include <paths.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <sysexits.h> | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "netstat.h" | #include "netstat.h" | ||||
#include "nl_defs.h" | #include "nl_defs.h" | ||||
#include <libxo/xo.h> | #include <libxo/xo.h> | ||||
static struct protox { | static struct protox { | ||||
int pr_index; /* index into nlist of cb head */ | int pr_index; /* index into nlist of cb head */ | ||||
int pr_sindex; /* index into nlist of stat block */ | int pr_sindex; /* index into nlist of stat block */ | ||||
▲ Show 20 Lines • Show All 208 Lines • ▼ Show 20 Lines | case 'C': | ||||
break; | break; | ||||
case 'd': | case 'd': | ||||
dflag = 1; | dflag = 1; | ||||
break; | break; | ||||
case 'F': | case 'F': | ||||
fib = strtol(optarg, &endptr, 0); | fib = strtol(optarg, &endptr, 0); | ||||
if (*endptr != '\0' || | if (*endptr != '\0' || | ||||
(fib == 0 && (errno == EINVAL || errno == ERANGE))) | (fib == 0 && (errno == EINVAL || errno == ERANGE))) | ||||
xo_errx(1, "%s: invalid fib", optarg); | xo_errx(EX_DATAERR, "%s: invalid fib", optarg); | ||||
break; | break; | ||||
case 'f': | case 'f': | ||||
if (strcmp(optarg, "inet") == 0) | if (strcmp(optarg, "inet") == 0) | ||||
af = AF_INET; | af = AF_INET; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
else if (strcmp(optarg, "inet6") == 0) | else if (strcmp(optarg, "inet6") == 0) | ||||
af = AF_INET6; | af = AF_INET6; | ||||
#endif | #endif | ||||
#ifdef IPSEC | #ifdef IPSEC | ||||
else if (strcmp(optarg, "pfkey") == 0) | else if (strcmp(optarg, "pfkey") == 0) | ||||
af = PF_KEY; | af = PF_KEY; | ||||
#endif | #endif | ||||
else if (strcmp(optarg, "unix") == 0 || | else if (strcmp(optarg, "unix") == 0 || | ||||
strcmp(optarg, "local") == 0) | strcmp(optarg, "local") == 0) | ||||
af = AF_UNIX; | af = AF_UNIX; | ||||
#ifdef NETGRAPH | #ifdef NETGRAPH | ||||
else if (strcmp(optarg, "ng") == 0 | else if (strcmp(optarg, "ng") == 0 | ||||
|| strcmp(optarg, "netgraph") == 0) | || strcmp(optarg, "netgraph") == 0) | ||||
af = AF_NETGRAPH; | af = AF_NETGRAPH; | ||||
#endif | #endif | ||||
else if (strcmp(optarg, "link") == 0) | else if (strcmp(optarg, "link") == 0) | ||||
af = AF_LINK; | af = AF_LINK; | ||||
else { | else { | ||||
xo_errx(1, "%s: unknown address family", | xo_errx(EX_DATAERR, "%s: unknown address family", | ||||
optarg); | optarg); | ||||
} | } | ||||
break; | break; | ||||
case 'g': | case 'g': | ||||
gflag = 1; | gflag = 1; | ||||
break; | break; | ||||
case 'h': | case 'h': | ||||
hflag = 1; | hflag = 1; | ||||
Show All 31 Lines | #endif | ||||
case 'O': | case 'O': | ||||
Oflag = 1; | Oflag = 1; | ||||
break; | break; | ||||
case 'P': | case 'P': | ||||
Pflag = 1; | Pflag = 1; | ||||
break; | break; | ||||
case 'p': | case 'p': | ||||
if ((tp = name2protox(optarg)) == NULL) { | if ((tp = name2protox(optarg)) == NULL) { | ||||
xo_errx(1, "%s: unknown or uninstrumented " | xo_errx(EX_DATAERR, "%s: unknown or uninstrumented " | ||||
"protocol", optarg); | "protocol", optarg); | ||||
} | } | ||||
pflag = 1; | pflag = 1; | ||||
break; | break; | ||||
case 'Q': | case 'Q': | ||||
Qflag = 1; | Qflag = 1; | ||||
break; | break; | ||||
case 'q': | case 'q': | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Discard setgid privileges if not the running kernel so that bad | * Discard setgid privileges if not the running kernel so that bad | ||||
* guys can't print interesting stuff from kernel memory. | * guys can't print interesting stuff from kernel memory. | ||||
*/ | */ | ||||
live = (nlistf == NULL && memf == NULL); | live = (nlistf == NULL && memf == NULL); | ||||
if (!live) { | if (!live) { | ||||
if (setgid(getgid()) != 0) | if (setgid(getgid()) != 0) | ||||
xo_err(-1, "setgid"); | xo_err(EX_OSERR, "setgid"); | ||||
des: `EX_OSERR` | |||||
Not Done Inline Actionsmain.c doesn't include sysexits.h. And most of the codes use the number instead of EXIT_ string. I may use the number style here to avoid too much change. bses30074_gmail.com: main.c doesn't include `sysexits.h`. And most of the codes use the number instead of `EXIT_`… | |||||
/* Load all necessary kvm symbols */ | /* Load all necessary kvm symbols */ | ||||
kresolve_list(nl); | kresolve_list(nl); | ||||
} | } | ||||
if (xflag && Tflag) | if (xflag && Tflag) | ||||
xo_errx(1, "-x and -T are incompatible, pick one."); | xo_errx(EX_USAGE, "-x and -T are incompatible, pick one."); | ||||
Not Done Inline ActionsEX_USAGE des: `EX_USAGE` | |||||
if (Bflag) { | if (Bflag) { | ||||
if (!live) | if (!live) | ||||
usage(); | usage(); | ||||
bpf_stats(interface); | bpf_stats(interface); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
Not Done Inline ActionsEX_IOERR des: `EX_IOERR` | |||||
exit(EX_OK); | |||||
Not Done Inline ActionsEX_OK des: `EX_OK` | |||||
} | } | ||||
if (mflag) { | if (mflag) { | ||||
if (!live) { | if (!live) { | ||||
if (kread(0, NULL, 0) == 0) | if (kread(0, NULL, 0) == 0) | ||||
mbpr(kvmd, nl[N_SFSTAT].n_value); | mbpr(kvmd, nl[N_SFSTAT].n_value); | ||||
} else | } else | ||||
mbpr(NULL, 0); | mbpr(NULL, 0); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
if (Qflag) { | if (Qflag) { | ||||
if (!live) { | if (!live) { | ||||
if (kread(0, NULL, 0) == 0) | if (kread(0, NULL, 0) == 0) | ||||
netisr_stats(); | netisr_stats(); | ||||
} else | } else | ||||
netisr_stats(); | netisr_stats(); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
#if 0 | #if 0 | ||||
/* | /* | ||||
* Keep file descriptors open to avoid overhead | * Keep file descriptors open to avoid overhead | ||||
* of open/close on each call to get* routines. | * of open/close on each call to get* routines. | ||||
*/ | */ | ||||
sethostent(1); | sethostent(1); | ||||
setnetent(1); | setnetent(1); | ||||
#else | #else | ||||
/* | /* | ||||
* This does not make sense any more with DNS being default over | * This does not make sense any more with DNS being default over | ||||
* the files. Doing a setXXXXent(1) causes a tcp connection to be | * the files. Doing a setXXXXent(1) causes a tcp connection to be | ||||
* used for the queries, which is slower. | * used for the queries, which is slower. | ||||
*/ | */ | ||||
#endif | #endif | ||||
if (iflag && !sflag) { | if (iflag && !sflag) { | ||||
xo_open_container("statistics"); | xo_open_container("statistics"); | ||||
intpr(NULL, af); | intpr(NULL, af); | ||||
xo_close_container("statistics"); | xo_close_container("statistics"); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
if (rflag) { | if (rflag) { | ||||
xo_open_container("statistics"); | xo_open_container("statistics"); | ||||
if (sflag) { | if (sflag) { | ||||
if (live) { | if (live) { | ||||
kresolve_list(nl); | kresolve_list(nl); | ||||
} | } | ||||
rt_stats(); | rt_stats(); | ||||
} else | } else | ||||
routepr(fib, af); | routepr(fib, af); | ||||
xo_close_container("statistics"); | xo_close_container("statistics"); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
if (oflag) { | if (oflag) { | ||||
xo_open_container("statistics"); | xo_open_container("statistics"); | ||||
nhops_print(fib, af); | nhops_print(fib, af); | ||||
xo_close_container("statistics"); | xo_close_container("statistics"); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
if (Oflag) { | if (Oflag) { | ||||
xo_open_container("statistics"); | xo_open_container("statistics"); | ||||
nhgrp_print(fib, af); | nhgrp_print(fib, af); | ||||
xo_close_container("statistics"); | xo_close_container("statistics"); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
if (gflag) { | if (gflag) { | ||||
xo_open_container("statistics"); | xo_open_container("statistics"); | ||||
if (sflag) { | if (sflag) { | ||||
if (af == AF_INET || af == AF_UNSPEC) | if (af == AF_INET || af == AF_UNSPEC) | ||||
mrt_stats(); | mrt_stats(); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (af == AF_INET6 || af == AF_UNSPEC) | if (af == AF_INET6 || af == AF_UNSPEC) | ||||
mrt6_stats(); | mrt6_stats(); | ||||
#endif | #endif | ||||
} else { | } else { | ||||
if (af == AF_INET || af == AF_UNSPEC) | if (af == AF_INET || af == AF_UNSPEC) | ||||
mroutepr(); | mroutepr(); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (af == AF_INET6 || af == AF_UNSPEC) | if (af == AF_INET6 || af == AF_UNSPEC) | ||||
mroute6pr(); | mroute6pr(); | ||||
#endif | #endif | ||||
} | } | ||||
xo_close_container("statistics"); | xo_close_container("statistics"); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
if (tp) { | if (tp) { | ||||
xo_open_container("statistics"); | xo_open_container("statistics"); | ||||
printproto(tp, tp->pr_name, &first); | printproto(tp, tp->pr_name, &first); | ||||
if (!first) | if (!first) | ||||
xo_close_list("socket"); | xo_close_list("socket"); | ||||
xo_close_container("statistics"); | xo_close_container("statistics"); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
xo_open_container("statistics"); | xo_open_container("statistics"); | ||||
if (af == AF_INET || af == AF_UNSPEC) | if (af == AF_INET || af == AF_UNSPEC) | ||||
for (tp = protox; tp->pr_name; tp++) | for (tp = protox; tp->pr_name; tp++) | ||||
printproto(tp, tp->pr_name, &first); | printproto(tp, tp->pr_name, &first); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (af == AF_INET6 || af == AF_UNSPEC) | if (af == AF_INET6 || af == AF_UNSPEC) | ||||
Show All 13 Lines | #endif /* NETGRAPH */ | ||||
if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) | if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) | ||||
unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, | unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, | ||||
nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, | nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, | ||||
nl[N_UNP_SPHEAD].n_value, &first); | nl[N_UNP_SPHEAD].n_value, &first); | ||||
if (!first) | if (!first) | ||||
xo_close_list("socket"); | xo_close_list("socket"); | ||||
xo_close_container("statistics"); | xo_close_container("statistics"); | ||||
xo_finish(); | if (xo_finish() < 0) | ||||
desUnsubmitted Not Done Inline ActionsIf you want, you can add a label here and replace every earlier occurrence of this and the next two lines with a goto to that label. But it's also fine as-is. des: If you want, you can add a label here and replace every earlier occurrence of this and the next… | |||||
exit(0); | xo_err(EX_IOERR, "stdout"); | ||||
exit(EX_OK); | |||||
} | } | ||||
static int | static int | ||||
fetch_stats_internal(const char *sysctlname, u_long off, void *stats, | fetch_stats_internal(const char *sysctlname, u_long off, void *stats, | ||||
size_t len, kreadfn_t kreadfn, int zero) | size_t len, kreadfn_t kreadfn, int zero) | ||||
{ | { | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
char errbuf[_POSIX2_LINE_MAX]; | char errbuf[_POSIX2_LINE_MAX]; | ||||
if (kvmd != NULL) | if (kvmd != NULL) | ||||
return (0); | return (0); | ||||
kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); | kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); | ||||
if (setgid(getgid()) != 0) | if (setgid(getgid()) != 0) | ||||
xo_err(-1, "setgid"); | xo_err(EX_OSERR, "setgid"); | ||||
if (kvmd == NULL) { | if (kvmd == NULL) { | ||||
xo_warnx("kvm not available: %s", errbuf); | xo_warnx("kvm not available: %s", errbuf); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Resolve symbol list, return 0 on success. | * Resolve symbol list, return 0 on success. | ||||
*/ | */ | ||||
static int | static int | ||||
kresolve_list(struct nlist *_nl) | kresolve_list(struct nlist *_nl) | ||||
{ | { | ||||
if ((kvmd == NULL) && (kvmd_init() != 0)) | if ((kvmd == NULL) && (kvmd_init() != 0)) | ||||
return (-1); | return (-1); | ||||
if (_nl[0].n_type != 0) | if (_nl[0].n_type != 0) | ||||
return (0); | return (0); | ||||
if (kvm_nlist(kvmd, _nl) < 0) { | if (kvm_nlist(kvmd, _nl) < 0) { | ||||
if (nlistf) | if (nlistf) | ||||
xo_errx(1, "%s: kvm_nlist: %s", nlistf, | xo_errx(EX_UNAVAILABLE, "%s: kvm_nlist: %s", nlistf, | ||||
kvm_geterr(kvmd)); | kvm_geterr(kvmd)); | ||||
else | else | ||||
xo_errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); | xo_errx(EX_UNAVAILABLE, "kvm_nlist: %s", kvm_geterr(kvmd)); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Wrapper of kvm_dpcpu_setcpu(). | * Wrapper of kvm_dpcpu_setcpu(). | ||||
*/ | */ | ||||
void | void | ||||
kset_dpcpu(u_int cpuid) | kset_dpcpu(u_int cpuid) | ||||
{ | { | ||||
if ((kvmd == NULL) && (kvmd_init() != 0)) | if ((kvmd == NULL) && (kvmd_init() != 0)) | ||||
xo_errx(-1, "%s: kvm is not available", __func__); | xo_errx(EX_UNAVAILABLE, "%s: kvm is not available", __func__); | ||||
if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0) | if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0) | ||||
xo_errx(-1, "%s: kvm_dpcpu_setcpu(%u): %s", __func__, | xo_errx(EX_UNAVAILABLE, "%s: kvm_dpcpu_setcpu(%u): %s", __func__, | ||||
cpuid, kvm_geterr(kvmd)); | cpuid, kvm_geterr(kvmd)); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Read kernel memory, return 0 on success. | * Read kernel memory, return 0 on success. | ||||
*/ | */ | ||||
int | int | ||||
Show All 40 Lines | kread_counters(u_long addr, void *buf, size_t size) | ||||
if (size % sizeof(uint64_t) != 0) { | if (size % sizeof(uint64_t) != 0) { | ||||
xo_warnx("kread_counters: invalid counter set size"); | xo_warnx("kread_counters: invalid counter set size"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
n = size / sizeof(uint64_t); | n = size / sizeof(uint64_t); | ||||
if ((counters = malloc(n * sizeof(u_long))) == NULL) | if ((counters = malloc(n * sizeof(u_long))) == NULL) | ||||
xo_err(-1, "malloc"); | xo_err(EX_OSERR, "malloc"); | ||||
if (kread(addr, counters, n * sizeof(u_long)) < 0) { | if (kread(addr, counters, n * sizeof(u_long)) < 0) { | ||||
free(counters); | free(counters); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
c = buf; | c = buf; | ||||
for (i = 0; i < n; i++) | for (i = 0; i < n; i++) | ||||
c[i] = kvm_counter_u64_fetch(kvmd, counters[i]); | c[i] = kvm_counter_u64_fetch(kvmd, counters[i]); | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | name2protox(const char *name) | ||||
} | } | ||||
endprotoent(); | endprotoent(); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
static void | static void | ||||
usage(void) | usage(void) | ||||
{ | { | ||||
(void)xo_error("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", | xo_error("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", | ||||
Not Done Inline ActionsThere is no need for a cast as xo_error() does not return anything. des: There is no need for a cast as `xo_error()` does not return anything. | |||||
"usage: netstat [-46AaCcLnRSTWx] [-f protocol_family | -p protocol]\n" | "usage: netstat [-46AaCcLnRSTWx] [-f protocol_family | -p protocol]\n" | ||||
" [-M core] [-N system]", | " [-M core] [-N system]", | ||||
" netstat -i | -I interface [-46abdhnW] [-f address_family]\n" | " netstat -i | -I interface [-46abdhnW] [-f address_family]\n" | ||||
" [-M core] [-N system]", | " [-M core] [-N system]", | ||||
" netstat -w wait [-I interface] [-46d] [-M core] [-N system]\n" | " netstat -w wait [-I interface] [-46d] [-M core] [-N system]\n" | ||||
" [-q howmany]", | " [-q howmany]", | ||||
" netstat -s [-46sz] [-f protocol_family | -p protocol]\n" | " netstat -s [-46sz] [-f protocol_family | -p protocol]\n" | ||||
" [-M core] [-N system]", | " [-M core] [-N system]", | ||||
" netstat -i | -I interface -s [-46s]\n" | " netstat -i | -I interface -s [-46s]\n" | ||||
" [-f protocol_family | -p protocol] [-M core] [-N system]", | " [-f protocol_family | -p protocol] [-M core] [-N system]", | ||||
" netstat -m [-M core] [-N system]", | " netstat -m [-M core] [-N system]", | ||||
" netstat -B [-z] [-I interface]", | " netstat -B [-z] [-I interface]", | ||||
" netstat -r [-46AnW] [-F fibnum] [-f address_family]\n" | " netstat -r [-46AnW] [-F fibnum] [-f address_family]\n" | ||||
" [-M core] [-N system]", | " [-M core] [-N system]", | ||||
" netstat -rs [-s] [-M core] [-N system]", | " netstat -rs [-s] [-M core] [-N system]", | ||||
" netstat -g [-46W] [-f address_family] [-M core] [-N system]", | " netstat -g [-46W] [-f address_family] [-M core] [-N system]", | ||||
" netstat -gs [-46s] [-f address_family] [-M core] [-N system]", | " netstat -gs [-46s] [-f address_family] [-M core] [-N system]", | ||||
" netstat -Q"); | " netstat -Q"); | ||||
xo_finish(); | exit(EX_USAGE); | ||||
Not Done Inline ActionsThere is no need to call xo_finish() here. des: There is no need to call `xo_finish()` here. | |||||
exit(1); | |||||
} | } | ||||
Not Done Inline ActionsEX_USAGE. des: `EX_USAGE`. |
EX_OSERR