mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-05 09:14:03 +00:00
Make netstat(1) to be aware of divert(4) sockets.
This commit is contained in:
parent
e52508ae0b
commit
cec335f937
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64192
@ -250,6 +250,6 @@ SYSCTL_NODE(_net_inet, IPPROTO_AH, ipsec, CTLFLAG_RW, 0, "IPSEC");
|
||||
#endif /* IPSEC */
|
||||
SYSCTL_NODE(_net_inet, IPPROTO_RAW, raw, CTLFLAG_RW, 0, "RAW");
|
||||
#ifdef IPDIVERT
|
||||
SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, div, CTLFLAG_RW, 0, "DIVERT");
|
||||
SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, divert, CTLFLAG_RW, 0, "DIVERT");
|
||||
#endif
|
||||
|
||||
|
@ -43,11 +43,13 @@
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
@ -356,6 +358,7 @@ div_attach(struct socket *so, int proto, struct proc *p)
|
||||
return error;
|
||||
inp = (struct inpcb *)so->so_pcb;
|
||||
inp->inp_ip_p = proto;
|
||||
inp->inp_vflag |= INP_IPV4;
|
||||
inp->inp_flags |= INP_HDRINCL;
|
||||
/* The socket is always "connected" because
|
||||
we always know "where" to send the packet */
|
||||
@ -446,6 +449,93 @@ div_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
return div_output(so, m, nam, control);
|
||||
}
|
||||
|
||||
static int
|
||||
div_pcblist(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error, i, n, s;
|
||||
struct inpcb *inp, **inp_list;
|
||||
inp_gen_t gencnt;
|
||||
struct xinpgen xig;
|
||||
|
||||
/*
|
||||
* The process of preparing the TCB list is too time-consuming and
|
||||
* resource-intensive to repeat twice on every request.
|
||||
*/
|
||||
if (req->oldptr == 0) {
|
||||
n = divcbinfo.ipi_count;
|
||||
req->oldidx = 2 * (sizeof xig)
|
||||
+ (n + n/8) * sizeof(struct xinpcb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (req->newptr != 0)
|
||||
return EPERM;
|
||||
|
||||
/*
|
||||
* OK, now we're committed to doing something.
|
||||
*/
|
||||
s = splnet();
|
||||
gencnt = divcbinfo.ipi_gencnt;
|
||||
n = divcbinfo.ipi_count;
|
||||
splx(s);
|
||||
|
||||
xig.xig_len = sizeof xig;
|
||||
xig.xig_count = n;
|
||||
xig.xig_gen = gencnt;
|
||||
xig.xig_sogen = so_gencnt;
|
||||
error = SYSCTL_OUT(req, &xig, sizeof xig);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
|
||||
if (inp_list == 0)
|
||||
return ENOMEM;
|
||||
|
||||
s = splnet();
|
||||
for (inp = divcbinfo.listhead->lh_first, i = 0; inp && i < n;
|
||||
inp = inp->inp_list.le_next) {
|
||||
if (inp->inp_gencnt <= gencnt && !prison_xinpcb(req->p, inp))
|
||||
inp_list[i++] = inp;
|
||||
}
|
||||
splx(s);
|
||||
n = i;
|
||||
|
||||
error = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
inp = inp_list[i];
|
||||
if (inp->inp_gencnt <= gencnt) {
|
||||
struct xinpcb xi;
|
||||
xi.xi_len = sizeof xi;
|
||||
/* XXX should avoid extra copy */
|
||||
bcopy(inp, &xi.xi_inp, sizeof *inp);
|
||||
if (inp->inp_socket)
|
||||
sotoxsocket(inp->inp_socket, &xi.xi_socket);
|
||||
error = SYSCTL_OUT(req, &xi, sizeof xi);
|
||||
}
|
||||
}
|
||||
if (!error) {
|
||||
/*
|
||||
* Give the user an updated idea of our state.
|
||||
* If the generation differs from what we told
|
||||
* her before, she knows that something happened
|
||||
* while we were processing this request, and it
|
||||
* might be necessary to retry.
|
||||
*/
|
||||
s = splnet();
|
||||
xig.xig_gen = divcbinfo.ipi_gencnt;
|
||||
xig.xig_sogen = so_gencnt;
|
||||
xig.xig_count = divcbinfo.ipi_count;
|
||||
splx(s);
|
||||
error = SYSCTL_OUT(req, &xig, sizeof xig);
|
||||
}
|
||||
free(inp_list, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
|
||||
SYSCTL_DECL(_net_inet_divert);
|
||||
SYSCTL_PROC(_net_inet_divert, OID_AUTO, pcblist, CTLFLAG_RD, 0, 0,
|
||||
div_pcblist, "S,xinpcb", "List of active divert sockets");
|
||||
|
||||
struct pr_usrreqs div_usrreqs = {
|
||||
div_abort, pru_accept_notsupp, div_attach, div_bind,
|
||||
pru_connect_notsupp, pru_connect2_notsupp, in_control, div_detach,
|
||||
|
Loading…
Reference in New Issue
Block a user