Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/sockstat/sockstat.c
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
#include <netinet/sctp.h> | #include <netinet/sctp.h> | ||||
#include <netinet/tcp.h> | #include <netinet/tcp.h> | ||||
#define TCPSTATES /* load state names */ | #define TCPSTATES /* load state names */ | ||||
#include <netinet/tcp_fsm.h> | #include <netinet/tcp_fsm.h> | ||||
#include <netinet/tcp_seq.h> | #include <netinet/tcp_seq.h> | ||||
#include <netinet/tcp_var.h> | #include <netinet/tcp_var.h> | ||||
#include <arpa/inet.h> | #include <arpa/inet.h> | ||||
#include <capsicum_helpers.h> | |||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <jail.h> | #include <jail.h> | ||||
#include <netdb.h> | #include <netdb.h> | ||||
#include <pwd.h> | #include <pwd.h> | ||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <libcasper.h> | |||||
#include <casper/cap_net.h> | |||||
#include <casper/cap_netdb.h> | |||||
#include <casper/cap_sysctl.h> | |||||
#define sstosin(ss) ((struct sockaddr_in *)(ss)) | #define sstosin(ss) ((struct sockaddr_in *)(ss)) | ||||
#define sstosin6(ss) ((struct sockaddr_in6 *)(ss)) | #define sstosin6(ss) ((struct sockaddr_in6 *)(ss)) | ||||
#define sstosun(ss) ((struct sockaddr_un *)(ss)) | #define sstosun(ss) ((struct sockaddr_un *)(ss)) | ||||
#define sstosa(ss) ((struct sockaddr *)(ss)) | #define sstosa(ss) ((struct sockaddr *)(ss)) | ||||
static int opt_4; /* Show IPv4 sockets */ | static int opt_4; /* Show IPv4 sockets */ | ||||
static int opt_6; /* Show IPv6 sockets */ | static int opt_6; /* Show IPv6 sockets */ | ||||
static int opt_C; /* Show congestion control */ | static int opt_C; /* Show congestion control */ | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
#define HASHSIZE 1009 | #define HASHSIZE 1009 | ||||
static struct sock *sockhash[HASHSIZE]; | static struct sock *sockhash[HASHSIZE]; | ||||
static struct xfile *xfiles; | static struct xfile *xfiles; | ||||
static int nxfiles; | static int nxfiles; | ||||
static cap_channel_t *capnet; | |||||
static cap_channel_t *capnetdb; | |||||
static cap_channel_t *capsysctl; | |||||
static int | static int | ||||
xprintf(const char *fmt, ...) | xprintf(const char *fmt, ...) | ||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
int len; | int len; | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
len = vprintf(fmt, ap); | len = vprintf(fmt, ap); | ||||
va_end(ap); | va_end(ap); | ||||
if (len < 0) | if (len < 0) | ||||
err(1, "printf()"); | err(1, "printf()"); | ||||
return (len); | return (len); | ||||
} | } | ||||
static int | static int | ||||
get_proto_type(const char *proto) | get_proto_type(const char *proto) | ||||
{ | { | ||||
struct protoent *pent; | struct protoent *pent; | ||||
if (strlen(proto) == 0) | if (strlen(proto) == 0) | ||||
return (0); | return (0); | ||||
pent = getprotobyname(proto); | pent = cap_getprotobyname(capnetdb, proto); | ||||
if (pent == NULL) { | if (pent == NULL) { | ||||
warn("getprotobyname"); | warn("cap_getprotobyname"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (pent->p_proto); | return (pent->p_proto); | ||||
} | } | ||||
static void | static void | ||||
init_protos(int num) | init_protos(int num) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | gather_sctp(void) | ||||
vflag = 0; | vflag = 0; | ||||
if (opt_4) | if (opt_4) | ||||
vflag |= INP_IPV4; | vflag |= INP_IPV4; | ||||
if (opt_6) | if (opt_6) | ||||
vflag |= INP_IPV6; | vflag |= INP_IPV6; | ||||
varname = "net.inet.sctp.assoclist"; | varname = "net.inet.sctp.assoclist"; | ||||
if (sysctlbyname(varname, 0, &len, 0, 0) < 0) { | if (cap_sysctlbyname(capsysctl, varname, 0, &len, 0, 0) < 0) { | ||||
if (errno != ENOENT) | if (errno != ENOENT) | ||||
err(1, "sysctlbyname()"); | err(1, "cap_sysctlbyname()"); | ||||
return; | return; | ||||
} | } | ||||
if ((buf = (char *)malloc(len)) == NULL) { | if ((buf = (char *)malloc(len)) == NULL) { | ||||
err(1, "malloc()"); | err(1, "malloc()"); | ||||
return; | return; | ||||
} | } | ||||
if (sysctlbyname(varname, buf, &len, 0, 0) < 0) { | if (cap_sysctlbyname(capsysctl, varname, buf, &len, 0, 0) < 0) { | ||||
err(1, "sysctlbyname()"); | err(1, "cap_sysctlbyname()"); | ||||
free(buf); | free(buf); | ||||
return; | return; | ||||
} | } | ||||
xinpcb = (struct xsctp_inpcb *)(void *)buf; | xinpcb = (struct xsctp_inpcb *)(void *)buf; | ||||
offset = sizeof(struct xsctp_inpcb); | offset = sizeof(struct xsctp_inpcb); | ||||
while ((offset < len) && (xinpcb->last == 0)) { | while ((offset < len) && (xinpcb->last == 0)) { | ||||
if ((sock = calloc(1, sizeof *sock)) == NULL) | if ((sock = calloc(1, sizeof *sock)) == NULL) | ||||
err(1, "malloc()"); | err(1, "malloc()"); | ||||
▲ Show 20 Lines • Show All 270 Lines • ▼ Show 20 Lines | gather_inet(int proto) | ||||
buf = NULL; | buf = NULL; | ||||
bufsize = 8192; | bufsize = 8192; | ||||
retry = 5; | retry = 5; | ||||
do { | do { | ||||
for (;;) { | for (;;) { | ||||
if ((buf = realloc(buf, bufsize)) == NULL) | if ((buf = realloc(buf, bufsize)) == NULL) | ||||
err(1, "realloc()"); | err(1, "realloc()"); | ||||
len = bufsize; | len = bufsize; | ||||
if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) | if (cap_sysctlbyname(capsysctl, varname, buf, &len, | ||||
NULL, 0) == 0) | |||||
break; | break; | ||||
if (errno == ENOENT) | if (errno == ENOENT) | ||||
goto out; | goto out; | ||||
if (errno != ENOMEM || len != bufsize) | if (errno != ENOMEM || len != bufsize) | ||||
err(1, "sysctlbyname()"); | err(1, "cap_sysctlbyname()"); | ||||
bufsize *= 2; | bufsize *= 2; | ||||
} | } | ||||
xig = (struct xinpgen *)buf; | xig = (struct xinpgen *)buf; | ||||
exig = (struct xinpgen *)(void *) | exig = (struct xinpgen *)(void *) | ||||
((char *)buf + len - sizeof *exig); | ((char *)buf + len - sizeof *exig); | ||||
if (xig->xig_len != sizeof *xig || | if (xig->xig_len != sizeof *xig || | ||||
exig->xig_len != sizeof *exig) | exig->xig_len != sizeof *exig) | ||||
errx(1, "struct xinpgen size mismatch"); | errx(1, "struct xinpgen size mismatch"); | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | gather_unix(int proto) | ||||
buf = NULL; | buf = NULL; | ||||
bufsize = 8192; | bufsize = 8192; | ||||
retry = 5; | retry = 5; | ||||
do { | do { | ||||
for (;;) { | for (;;) { | ||||
if ((buf = realloc(buf, bufsize)) == NULL) | if ((buf = realloc(buf, bufsize)) == NULL) | ||||
err(1, "realloc()"); | err(1, "realloc()"); | ||||
len = bufsize; | len = bufsize; | ||||
if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) | if (cap_sysctlbyname(capsysctl, varname, buf, &len, | ||||
NULL, 0) == 0) | |||||
break; | break; | ||||
if (errno != ENOMEM || len != bufsize) | if (errno != ENOMEM || len != bufsize) | ||||
err(1, "sysctlbyname()"); | err(1, "cap_sysctlbyname()"); | ||||
bufsize *= 2; | bufsize *= 2; | ||||
} | } | ||||
xug = (struct xunpgen *)buf; | xug = (struct xunpgen *)buf; | ||||
exug = (struct xunpgen *)(void *) | exug = (struct xunpgen *)(void *) | ||||
((char *)buf + len - sizeof(*exug)); | ((char *)buf + len - sizeof(*exug)); | ||||
if (xug->xug_len != sizeof(*xug) || | if (xug->xug_len != sizeof(*xug) || | ||||
exug->xug_len != sizeof(*exug)) { | exug->xug_len != sizeof(*exug)) { | ||||
warnx("struct xinpgen size mismatch"); | warnx("struct xinpgen size mismatch"); | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
getfiles(void) | getfiles(void) | ||||
{ | { | ||||
size_t len, olen; | size_t len, olen; | ||||
olen = len = sizeof(*xfiles); | olen = len = sizeof(*xfiles); | ||||
if ((xfiles = malloc(len)) == NULL) | if ((xfiles = malloc(len)) == NULL) | ||||
err(1, "malloc()"); | err(1, "malloc()"); | ||||
while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) { | while (cap_sysctlbyname(capsysctl, "kern.file", xfiles, &len, 0, 0) | ||||
== -1) { | |||||
if (errno != ENOMEM || len != olen) | if (errno != ENOMEM || len != olen) | ||||
err(1, "sysctlbyname()"); | err(1, "cap_sysctlbyname()"); | ||||
olen = len *= 2; | olen = len *= 2; | ||||
if ((xfiles = realloc(xfiles, len)) == NULL) | if ((xfiles = realloc(xfiles, len)) == NULL) | ||||
err(1, "realloc()"); | err(1, "realloc()"); | ||||
} | } | ||||
if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) | if (len > 0 && xfiles->xf_size != sizeof(*xfiles)) | ||||
errx(1, "struct xfile size mismatch"); | errx(1, "struct xfile size mismatch"); | ||||
nxfiles = len / sizeof(*xfiles); | nxfiles = len / sizeof(*xfiles); | ||||
} | } | ||||
Show All 17 Lines | case AF_INET6: | ||||
port = ntohs(sstosin6(ss)->sin6_port); | port = ntohs(sstosin6(ss)->sin6_port); | ||||
break; | break; | ||||
case AF_UNIX: | case AF_UNIX: | ||||
sun = sstosun(ss); | sun = sstosun(ss); | ||||
off = (int)((char *)&sun->sun_path - (char *)sun); | off = (int)((char *)&sun->sun_path - (char *)sun); | ||||
return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); | return (xprintf("%.*s", sun->sun_len - off, sun->sun_path)); | ||||
} | } | ||||
if (addrstr[0] == '\0') { | if (addrstr[0] == '\0') { | ||||
error = getnameinfo(sstosa(ss), ss->ss_len, addrstr, | error = cap_getnameinfo(capnet, sstosa(ss), ss->ss_len, | ||||
sizeof(addrstr), NULL, 0, NI_NUMERICHOST); | addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST); | ||||
if (error) | if (error) | ||||
errx(1, "getnameinfo()"); | errx(1, "cap_getnameinfo()"); | ||||
} | } | ||||
if (port == 0) | if (port == 0) | ||||
return xprintf("%s:*", addrstr); | return xprintf("%s:*", addrstr); | ||||
else | else | ||||
return xprintf("%s:%d", addrstr, port); | return xprintf("%s:%d", addrstr, port); | ||||
} | } | ||||
static const char * | static const char * | ||||
getprocname(pid_t pid) | getprocname(pid_t pid) | ||||
{ | { | ||||
static struct kinfo_proc proc; | static struct kinfo_proc proc; | ||||
size_t len; | size_t len; | ||||
int mib[4]; | int mib[4]; | ||||
mib[0] = CTL_KERN; | mib[0] = CTL_KERN; | ||||
mib[1] = KERN_PROC; | mib[1] = KERN_PROC; | ||||
mib[2] = KERN_PROC_PID; | mib[2] = KERN_PROC_PID; | ||||
mib[3] = (int)pid; | mib[3] = (int)pid; | ||||
len = sizeof(proc); | len = sizeof(proc); | ||||
if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { | if (cap_sysctl(capsysctl, mib, nitems(mib), &proc, &len, NULL, 0) | ||||
== -1) { | |||||
/* Do not warn if the process exits before we get its name. */ | /* Do not warn if the process exits before we get its name. */ | ||||
if (errno != ESRCH) | if (errno != ESRCH) | ||||
warn("sysctl()"); | warn("cap_sysctl()"); | ||||
return ("??"); | return ("??"); | ||||
} | } | ||||
return (proc.ki_comm); | return (proc.ki_comm); | ||||
} | } | ||||
static int | static int | ||||
getprocjid(pid_t pid) | getprocjid(pid_t pid) | ||||
{ | { | ||||
static struct kinfo_proc proc; | static struct kinfo_proc proc; | ||||
size_t len; | size_t len; | ||||
int mib[4]; | int mib[4]; | ||||
mib[0] = CTL_KERN; | mib[0] = CTL_KERN; | ||||
mib[1] = KERN_PROC; | mib[1] = KERN_PROC; | ||||
mib[2] = KERN_PROC_PID; | mib[2] = KERN_PROC_PID; | ||||
mib[3] = (int)pid; | mib[3] = (int)pid; | ||||
len = sizeof(proc); | len = sizeof(proc); | ||||
if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) { | if (cap_sysctl(capsysctl, mib, nitems(mib), &proc, &len, NULL, 0) | ||||
== -1) { | |||||
/* Do not warn if the process exits before we get its jid. */ | /* Do not warn if the process exits before we get its jid. */ | ||||
if (errno != ESRCH) | if (errno != ESRCH) | ||||
warn("sysctl()"); | warn("cap_sysctl()"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (proc.ki_jid); | return (proc.ki_jid); | ||||
} | } | ||||
static int | static int | ||||
check_ports(struct sock *s) | check_ports(struct sock *s) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 319 Lines • ▼ Show 20 Lines | set_default_protos(void) | ||||
struct protoent *prot; | struct protoent *prot; | ||||
const char *pname; | const char *pname; | ||||
size_t pindex; | size_t pindex; | ||||
init_protos(default_numprotos); | init_protos(default_numprotos); | ||||
for (pindex = 0; pindex < default_numprotos; pindex++) { | for (pindex = 0; pindex < default_numprotos; pindex++) { | ||||
pname = default_protos[pindex]; | pname = default_protos[pindex]; | ||||
prot = getprotobyname(pname); | prot = cap_getprotobyname(capnetdb, pname); | ||||
if (prot == NULL) | if (prot == NULL) | ||||
err(1, "getprotobyname: %s", pname); | err(1, "cap_getprotobyname: %s", pname); | ||||
protos[pindex] = prot->p_proto; | protos[pindex] = prot->p_proto; | ||||
} | } | ||||
numprotos = pindex; | numprotos = pindex; | ||||
return (pindex); | return (pindex); | ||||
} | } | ||||
/* | /* | ||||
* Return the vnet property of the jail, or -1 on error. | * Return the vnet property of the jail, or -1 on error. | ||||
Show All 33 Lines | usage(void) | ||||
fprintf(stderr, | fprintf(stderr, | ||||
"usage: sockstat [-46cLlSsUuvw] [-j jid] [-p ports] [-P protocols]\n"); | "usage: sockstat [-46cLlSsUuvw] [-j jid] [-p ports] [-P protocols]\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
cap_channel_t *capcas; | |||||
cap_net_limit_t *limit; | |||||
int protos_defined = -1; | int protos_defined = -1; | ||||
int o, i; | int o, i; | ||||
opt_j = -1; | opt_j = -1; | ||||
while ((o = getopt(argc, argv, "46Ccj:Llnp:P:qSsUuvw")) != -1) | while ((o = getopt(argc, argv, "46Ccj:Llnp:P:qSsUuvw")) != -1) | ||||
switch (o) { | switch (o) { | ||||
case '4': | case '4': | ||||
opt_4 = 1; | opt_4 = 1; | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | case JAIL_SYS_NEW: | ||||
err(3, "jail_attach()"); | err(3, "jail_attach()"); | ||||
/* Set back to -1 for normal output in vnet jail. */ | /* Set back to -1 for normal output in vnet jail. */ | ||||
opt_j = -1; | opt_j = -1; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
capcas = cap_init(); | |||||
if (capcas == NULL) | |||||
err(1, "Unable to contact Casper"); | |||||
if (caph_enter_casper() < 0) | |||||
err(1, "Unable to enter capability mode"); | |||||
capnet = cap_service_open(capcas, "system.net"); | |||||
if (capnet == NULL) | |||||
err(1, "Unable to open system.net service"); | |||||
capnetdb = cap_service_open(capcas, "system.netdb"); | |||||
if (capnetdb == NULL) | |||||
oshogbo: copy paste error. | |||||
err(1, "Unable to open system.netdb service"); | |||||
capsysctl = cap_service_open(capcas, "system.sysctl"); | |||||
if (capsysctl == NULL) | |||||
err(1, "Unable to open system.sysctl service"); | |||||
cap_close(capcas); | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
Done Inline Actions-1 ? Shouldn't be CAPNET_ADDR2NAME ? oshogbo: -1 ? Shouldn't be CAPNET_ADDR2NAME ? | |||||
if (limit == NULL) | |||||
err(1, "Unable to init cap_net limits"); | |||||
if (cap_net_limit(limit) < 0) | |||||
err(1, "Unable to apply limits"); | |||||
if ((!opt_4 && !opt_6) && protos_defined != -1) | if ((!opt_4 && !opt_6) && protos_defined != -1) | ||||
opt_4 = opt_6 = 1; | opt_4 = opt_6 = 1; | ||||
if (!opt_4 && !opt_6 && !opt_u) | if (!opt_4 && !opt_6 && !opt_u) | ||||
opt_4 = opt_6 = opt_u = 1; | opt_4 = opt_6 = opt_u = 1; | ||||
if ((opt_4 || opt_6) && protos_defined == -1) | if ((opt_4 || opt_6) && protos_defined == -1) | ||||
protos_defined = set_default_protos(); | protos_defined = set_default_protos(); | ||||
if (!opt_c && !opt_l) | if (!opt_c && !opt_l) | ||||
Show All 19 Lines |
copy paste error.